home *** CD-ROM | disk | FTP | other *** search
/ Amiga Inside! / Amiga FD Inside (1995)(Ultramax).iso / berndspd / devtools / intuigen / intuigenlibs / igrequest.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-22  |  58.7 KB  |  2,349 lines

  1. /*
  2. IGRequest.c
  3.  
  4. (C) Copyright 1993 Justin Miller
  5.     This file is part of the IntuiGen package.
  6.     Use of this code is pursuant to the license outlined in
  7.     COPYRIGHT.txt, included with the IntuiGen package.
  8.  
  9.     As per COPYRIGHT.txt:
  10.  
  11.     1)  This file may be freely distributed providing that
  12.         it is unmodified, and included in a complete IntuiGen
  13.         2.0 package (it may not be distributed alone).
  14.  
  15.     2)  Programs using this code may not be distributed unless
  16.         their author has paid the Shareware fee for IntuiGen 2.0.
  17. */
  18.  
  19.  
  20. #include <stddef.h>
  21. #include <stdlib.h>
  22. #include <exec/exec.h>
  23. #include <exec/tasks.h>
  24. #include <dos/dos.h>
  25. #include <dos/dosextens.h>
  26. #include <intuition/intuition.h>
  27. #include <IntuiGen/IntuiGen.h>
  28. #include <devices/keymap.h>
  29. #include <devices/inputevent.h>
  30. #include <devices/console.h>
  31. #include <rexx/rxslib.h>
  32. #include <clib/exec_protos.h>
  33. #include <clib/intuition_protos.h>
  34. #include <clib/graphics_protos.h>
  35. #include <clib/alib_protos.h>
  36.  
  37. struct IGPrivate {
  38.     struct Requester *BlockingReq;
  39.     SHORT BlockedCount;
  40. };
  41.  
  42.  
  43. /* if you do not need the provisions to convert string gadget entries
  44.  * to floats, comment the next line out
  45. */
  46.  
  47. /* #define FLOATINGMATH TRUE */
  48.  
  49.  
  50.  
  51. /* If you don't need to use the ARexx features comment this out. */
  52.  
  53. /* #define REXX TRUE */
  54.  
  55.  
  56.  
  57. /* If you don't need to use prop gadgets, comment this out.  */
  58.  
  59. #define PROPS TRUE
  60.  
  61.  
  62. /* If you plan to make use of SelectBoxes (list boxes), leave this defined.
  63.  *  for more compact code, comment it out.  Requires Props (above).
  64. */
  65.  
  66. #define SBOXES TRUE
  67.  
  68.  
  69.  
  70. /* If you are trying to compile a small memory model program, IGRequest
  71.     can be a lot of over head.    To make it __far, uncomment the next line.
  72.     Make sure that you define IGFAR before you include IGRequest.h! */
  73.  
  74. /*
  75. #define IGFAR TRUE
  76. */
  77.  
  78.  
  79.  
  80.  
  81. /* define these however you want, depending on your routines and
  82.  * your compiler, and the type of floating point you want to use
  83. */
  84.  
  85. #define LongToString(s,l) (sprintf((s),"%d",(l)))
  86. #define FloatToString(s,f) (sprintf((s),"%f",(f)))
  87. typedef float IGFloat;
  88.  
  89.  
  90.  
  91.  
  92. extern APTR IntuitionBase;
  93. extern APTR GfxBase;
  94.  
  95. /* extern APTR MathBase; */
  96. /* You may need this when using math, depending on your compiler */
  97.  
  98.  
  99.  
  100. /* String handling routines for string gadgets */
  101.  
  102. int cismember (char c,char *set)
  103. /* returns true if c is in set */
  104. {
  105.     short i;
  106.     for (i=0;set[i];++i)
  107.     if (set[i]==c) return (++i);
  108.     return (0);
  109. }
  110.  
  111. void delchars (char *s,USHORT p,USHORT n)
  112. /* deletes n chars starting at position p from string s */
  113. {
  114.     n+=p;
  115.     if (n>strlen(s)) n=strlen(s);
  116.     do {
  117.     s[p++]=s[n];
  118.     } while (s[n++]);
  119. }
  120.  
  121. BOOL strelim (char *s,char *elim,BOOL k)
  122. /* when k is true, only chars in elim allowed, otherwise,
  123.  * only chars not in elim allowed */
  124. {
  125.     SHORT i=-1;
  126.     BOOL f=0;
  127.  
  128.     while (s[++i])
  129.     if ((cismember(s[i],elim) && !k)||(!cismember(s[i],elim) && k)) {
  130.         f=1;
  131.         delchars (s,i--,1);
  132.     }
  133.     return (f);
  134. }
  135.  
  136.  
  137. UBYTE InterpretDKey(UBYTE *start,UBYTE *descrip)
  138. {
  139.     if (*descrip & DPF_DEAD) return(0);
  140.     if (*descrip==0) { ++descrip; return(*descrip); }
  141.     if (*descrip & DPF_MOD) {
  142.     ++descrip;
  143.     descrip=start + *descrip;
  144.     return (*descrip);
  145.     }
  146.     return (0);
  147. }
  148.  
  149.  
  150.  
  151. /* Takes RAWKEY code and qualifier (from an IntuiMessage) and returns
  152.    ASCII equivalent
  153. */
  154.  
  155. UBYTE RawKeyToAscii (USHORT code,USHORT qual)
  156. {
  157.     UBYTE key=0;
  158.     USHORT r;
  159.     struct MsgPort *port=0;
  160.     struct IOStdReq *req=0;
  161.     struct KeyMap *km=0;
  162.     ULONG *kmentry;
  163.     UBYTE *kmflags;
  164.     UBYTE *kmdkey,*kmdstart;
  165.     UBYTE *kmcaps;
  166.  
  167.     if (code>0x67) return (0);
  168.  
  169.     port=CreatePort(0,0);
  170.     if (!port) goto error;
  171.     req=CreateStdIO(port);
  172.     if (!req) goto error;
  173.  
  174.     km=AllocMem(sizeof(struct KeyMap),MEMF_PUBLIC | MEMF_CLEAR);
  175.     if (!km) goto error;
  176.  
  177.     if (OpenDevice("console.device",-1,req,0)) goto error;
  178.     req->io_Command=CD_ASKDEFAULTKEYMAP;
  179.     req->io_Length=sizeof(struct KeyMap);
  180.     req->io_Data=km;
  181.     DoIO(req);
  182.     if (req->io_Error) { CloseDevice(req); goto error; }
  183.  
  184.     if (code>0x3f) {
  185.     kmflags=km->km_HiKeyMapTypes;
  186.     kmentry=km->km_HiKeyMap;
  187.     kmcaps=km->km_HiCapsable;
  188.     } else {
  189.     kmflags=km->km_LoKeyMapTypes;
  190.     kmentry=km->km_LoKeyMap;
  191.     kmcaps=km->km_LoCapsable;
  192.     }
  193.  
  194.     if (code>0x3f) code-=0x40;
  195.  
  196.     if (qual & IEQUALIFIER_CAPSLOCK) {
  197.     UBYTE byt,bit;
  198.     byt=code/8;
  199.     bit=code%8;
  200.     if (kmcaps[byt] & bit) qual|=IEQUALIFIER_LSHIFT;
  201.     }
  202.  
  203.     if (kmflags[code] & KCF_STRING) { CloseDevice(req); goto error; }
  204.     if (kmflags[code] & KCF_DEAD) {
  205.  
  206.     kmdkey=kmdstart=(UBYTE *)kmentry[code];
  207.  
  208.     if ( ( qual & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT) ) && (kmflags[code] & KCF_SHIFT) ) {
  209.         kmdkey+=2;
  210.         if ( ( qual & (IEQUALIFIER_LALT | IEQUALIFIER_RALT) ) && (kmflags[code] & KCF_ALT) ) {
  211.         kmdkey+=4;
  212.         key=InterpretDKey(kmdstart,kmdkey);
  213.         } else key=InterpretDKey(kmdstart,kmdkey);
  214.     } else if ( ( qual & (IEQUALIFIER_LALT | IEQUALIFIER_RALT) ) && (kmflags[code] & KCF_ALT) ) {
  215.         kmdkey+=4;
  216.         key=InterpretDKey(kmdstart,kmdkey);
  217.     } else { key=InterpretDKey(kmdstart,kmdkey); }
  218.  
  219.     } else {
  220.     if (qual & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) {
  221.         if (qual & (IEQUALIFIER_LALT | IEQUALIFIER_RALT)) {
  222.         key=(kmentry[code] & 0xff000000) >> 24;
  223.         } else key=(kmentry[code] & 0xff00) >> 8;
  224.     } else if (qual & (IEQUALIFIER_LALT | IEQUALIFIER_RALT))
  225.         key=(kmentry[code] & 0xff0000) >> 16;
  226.     else { key=kmentry[code] & 0xff; }
  227.     }
  228.  
  229.     if (qual & IEQUALIFIER_CONTROL) key&=159;
  230.  
  231.     CloseDevice(req);
  232. error: if (req) DeleteStdIO (req);
  233.        if (port) DeletePort (port);
  234.        if (km) FreeMem(km,sizeof (struct KeyMap));
  235.        return (key);
  236. }
  237.  
  238.  
  239. /* Takes ASCII char and returns Rawkey code.  ASCII code must correspond to
  240.    letter painted on keyboard keycap (the unqualified value).  Qualifier
  241.    must be determined as follows (Under IGRequest which does not
  242.    differentiate between right and left):
  243.  
  244.     SHIFT =  1
  245.     ALT   = 16
  246.     CTRL  =  8
  247.     AMIGA = 64
  248.  
  249.    Returns -1 error.
  250. */
  251.  
  252. SHORT ASCIIToRawKey (char c)
  253. {
  254.     UBYTE b;
  255.     SHORT r=-1;
  256.     struct MsgPort *port=0;
  257.     struct IOStdReq *req=0;
  258.     struct KeyMap *km=0;
  259.     ULONG *kmentry;
  260.     UBYTE *kmflags,*kmdkey;
  261.  
  262.     if (c>='A' && c<='Z') c+='a'-'A';
  263.  
  264.     port=CreatePort(0,0);
  265.     if (!port) goto error;
  266.     req=CreateStdIO(port);
  267.     if (!req) goto error;
  268.     km=AllocMem (sizeof(struct KeyMap),MEMF_PUBLIC | MEMF_CLEAR);
  269.     if (!km) goto error;
  270.  
  271.     if (OpenDevice("console.device",-1,req,0)) goto error;
  272.     req->io_Command=CD_ASKDEFAULTKEYMAP;
  273.     req->io_Length=sizeof(struct KeyMap);
  274.     req->io_Data=km;
  275.     DoIO(req);
  276.     if (req->io_Error) { CloseDevice (req); goto error; }
  277.  
  278.     kmentry = km->km_LoKeyMap;
  279.     kmflags = km->km_LoKeyMapTypes;
  280.  
  281.     for (r=0;r<0x40;++r,++kmentry,++kmflags) {
  282.     if (*kmflags & KCF_STRING) continue;
  283.     if (*kmflags & KCF_DEAD) {
  284.         kmdkey=(UBYTE *)(kmentry[0]);
  285.         b=InterpretDKey(kmdkey,kmdkey);
  286.         if (b==c) break;
  287.     } else if ((kmentry[0] & 0xff) == c) break;
  288.     }
  289.     if (r==0x40) {
  290.     kmentry = km->km_HiKeyMap;
  291.     kmflags = km->km_HiKeyMapTypes;
  292.     for (;r<0x68;++r,++kmentry,++kmflags) {
  293.         if (*kmflags & KCF_STRING) continue;
  294.         if (*kmflags & KCF_DEAD) {
  295.         kmdkey=(UBYTE *)(kmentry[0]);
  296.         b=InterpretDKey(kmdkey,kmdkey);
  297.         if (b==c) break;
  298.         } else if ((kmentry[0] & 0xff) == c) break;
  299.     }
  300.     }
  301.     if (r>0x67) r=-1;
  302.  
  303.     CloseDevice(req);
  304. error: if (req) DeleteStdIO (req);
  305.        if (port) DeletePort (port);
  306.        if (km) FreeMem (km,sizeof(struct KeyMap));
  307.        return (r);
  308. }
  309.  
  310.  
  311. /* Procedure IGInitRequester */
  312.  
  313. void IGInitRequester (struct Window *win,    /* Window values relative to */
  314.               struct Requester *req, /* Intuition Requester */
  315.               SHORT rl, SHORT rr,    /* Left, right offsets from
  316.                           * Window edge */
  317.               SHORT rt,SHORT rb)     /* Top, Bottom offsets from
  318.                           * Window edge */
  319. /*  NOTE: This routine calls Intuition's InitRequest, clearing any
  320.  *   data values previously in requester */
  321. {
  322.         InitRequester (req);
  323.         req->LeftEdge=rl;
  324.         req->TopEdge=rt;
  325.         req->Width=win->Width-rl-rr;
  326.         req->Height=win->Height-rt-rb;
  327. }
  328.  
  329.  
  330.  
  331.  
  332. /* for InitRequesterToOpen */
  333.  
  334. #define RSOF 2 /* Number of pixels to leave on sides of window */
  335. #define RTOF 12 /* Number of pixels to leave on top */
  336. #define RBOF 2 /* Number of pixels to leave on bottom */
  337.  
  338.  
  339.  
  340.  
  341. /* LookUp Table for IDCMP functions */
  342.  
  343. static ULONG ftable[]={ offsetof(struct IGRequest,SizeVerify),
  344.     offsetof(struct IGRequest,NewSize), offsetof(struct IGRequest,RefreshWindow),
  345.     offsetof(struct IGRequest,MouseButtons), offsetof(struct IGRequest,MouseMove),
  346.     offsetof(struct IGRequest,GDownFunction), offsetof(struct IGRequest,GUpFunction),
  347.     offsetof(struct IGRequest,ReqSet), offsetof(struct IGRequest,MenuPick),
  348.     offsetof(struct IGRequest,CloseWindow), offsetof(struct IGRequest,RawKey),
  349.     offsetof(struct IGRequest,ReqVerify), offsetof(struct IGRequest,ReqClear),
  350.     offsetof(struct IGRequest,MenuVerify),offsetof(struct IGRequest,NewPrefs),
  351.     offsetof(struct IGRequest,DiskInserted), offsetof(struct IGRequest,DiskRemoved),
  352.     /* WBenchMessage */ NULL, offsetof(struct IGRequest,ActiveWindow),
  353.     offsetof(struct IGRequest,InActiveWindow), offsetof(struct IGRequest,DeltaMove),
  354.     /* VanillaKey */ NULL, offsetof(struct IGRequest,IntuiTicks)
  355. };
  356.  
  357.  
  358. #ifdef PROPS
  359.  
  360. /* Procedure FixIGProps
  361.  * Fixes all links between Prop Gadgets, their arrows, and SelectBoxes.
  362.  * Only links in IGPropInfo struct for each Prop Gadget need be initialized.
  363.  * Ignores Non-Prop Gadgets
  364. */
  365.  
  366. void FixIGProps (struct Gadget *base)
  367. {
  368.     struct SelectBox *sbox;
  369.     struct IGPropArrowInfo *ainfo;
  370.     struct IGPropInfo *igpinfo;
  371.     struct Gadget *gadg;
  372.  
  373.     while (base) {
  374.     if ((base->GadgetType==GTYP_PROPGADGET) && base->UserData) {
  375.         igpinfo=(struct IGPropInfo *)base->UserData;
  376.         gadg=igpinfo->LUArrow;
  377.         ainfo=(struct IGPropArrowInfo *)gadg->UserData;
  378.         if (ainfo) ainfo->Prop=base;
  379.         gadg=igpinfo->RDArrow;
  380.         ainfo=(struct IGPropArrowInfo *)gadg->UserData;
  381.         if (ainfo) ainfo->Prop=base;
  382.         if (igpinfo->SBox) {
  383.         sbox=igpinfo->SBox;
  384.         sbox->Prop=base;
  385.         }
  386.     }
  387.     base=base->NextGadget;
  388.     }
  389. }
  390.  
  391.  
  392.  
  393.  
  394. /* Procedure ModifyIGProp */
  395. /* Sets IG Prop Gadget values to those specified in args,
  396.  * refreshes Prop Gadget
  397. */
  398.  
  399. void ModifyIGProp (struct IGRequest *req,
  400.            struct Gadget *prop,
  401.            USHORT mx,my,dx,dy,
  402.            USHORT top,left)
  403. {
  404.     struct IGPropInfo *igpinfo;
  405.     struct PropInfo *pinfo;
  406.  
  407.     if (!req || !prop) return ();
  408.  
  409.     pinfo=(struct PropInfo *)prop->SpecialInfo;
  410.     igpinfo=(struct IGPropInfo *)prop->UserData;
  411.  
  412.     if (!pinfo || !igpinfo) return ();
  413.     igpinfo->MaxX=mx;          igpinfo->MaxY=my;
  414.     igpinfo->DisplayedX=dx;   igpinfo->DisplayedY=dy;
  415.     igpinfo->Top=top;          igpinfo->Left=left;
  416.  
  417.     if (dx>mx) mx=dx;
  418.     if (dy>my) my=dy;
  419.     pinfo->HorizBody=(0xffff*dx)/mx;
  420.     pinfo->VertBody=(0xffff*dy)/my;
  421.     if (mx>dx)
  422.     pinfo->HorizPot=(ULONG)((ULONG)left*0xffff/(mx-dx));
  423.     else pinfo->HorizPot=0;
  424.     if (my>dy)
  425.     pinfo->VertPot=(ULONG)((ULONG)top*0xffff/(my-dy));
  426.     else pinfo->VertPot=0;
  427.     if (req->Window) RefreshGList (prop,req->Window,req->Requester,1);
  428. }
  429.  
  430. #endif /* PROPS */
  431.  
  432. static struct TextAttr Attr={
  433.     "topaz.font",TOPAZ_EIGHTY,NULL,FPF_ROMFONT
  434. };
  435.  
  436. static struct IntuiText Template={
  437.     1,0,JAM2,0,0,&Attr,0,0
  438. };
  439.  
  440.  
  441.  
  442. #ifdef SBOXES
  443.  
  444.  
  445. /* This Function Should fill in the ScrollFunc field of any prop gadgets
  446.  * associated with a SelectBox
  447. */
  448. void UpdateSBox (struct IGRequest *req, struct Gadget *gadg,
  449.         LONG x,LONG y)
  450. {
  451.     struct IGPropInfo *igpinfo;
  452.     struct SelectBox *sbox;
  453.     struct IntuiText text;
  454.     struct SelectBoxEntry *entry,*e2;
  455.     struct IGSBoxGadgetInfo *einfo;
  456.     BYTE oldpen,oldmode,oldfgpen;
  457.     UBYTE string[100];
  458.     text=Template;
  459.  
  460.     igpinfo=(struct IGPropInfo *)gadg->UserData;
  461.     sbox=igpinfo->SBox;
  462.     einfo=(struct IGSBoxGadgetInfo *)sbox->GList->UserData;
  463.     entry=einfo->Entry;
  464.  
  465.     for (e2=entry,x=0;x<sbox->Displayed && e2;++x,e2=e2->Next)
  466.     e2->Gadget=0;
  467.  
  468.     while (entry && entry->Prev && y<entry->ID) entry=entry->Prev;
  469.     while (entry && entry->Next && y>entry->ID) entry=entry->Next;
  470.  
  471.     oldfgpen=req->Window->RPort->FgPen;
  472.     oldmode=req->Window->RPort->DrawMode;
  473.     oldpen=req->Window->RPort->BgPen;
  474.     SetBPen (req->Window->RPort,0);
  475.     SetDrMd (req->Window->RPort,JAM2);
  476.  
  477.     text.IText=string;
  478.  
  479.     for (y=0;y<sbox->Displayed;++y) {
  480.     einfo=(struct IGSBoxGadgetInfo *)sbox->GList[y].UserData;
  481.     sbox->GList[y].Flags=GFLG_GADGHCOMP;
  482.     einfo->Entry=entry;
  483.     SetAPen (req->Window->RPort,0);
  484.     RectFill (req->Window->RPort,sbox->GList[y].LeftEdge,
  485.         sbox->GList[y].TopEdge,sbox->GList[y].LeftEdge+sbox->GList[y].Width,
  486.         sbox->GList[y].TopEdge+sbox->GList[y].Height);
  487.     if (entry) {
  488.         SetAPen (req->Window->RPort,1);
  489.         entry->Gadget=&(sbox->GList[y]);
  490.         text.LeftEdge=sbox->GList[y].LeftEdge;
  491.         text.TopEdge=sbox->GList[y].TopEdge+1;
  492.         text.FrontPen=entry->Color;
  493.         strcpy (string,entry->Text);
  494.         while (IntuiTextLength(&text)>sbox->Width-6)
  495.         string[strlen(string)-1]=0;
  496.         PrintIText (req->Window->RPort,&text,0,0);
  497.     }
  498.     if (entry && entry->Flags & SB_SELECTED) {
  499.         sbox->GList[y].Flags=GFLG_SELECTED | GFLG_GADGHCOMP;
  500.         req->Window->RPort->BgPen=1;
  501.         SetDrMd (req->Window->RPort,COMPLEMENT | INVERSVID | JAM2);
  502.         RectFill (req->Window->RPort,sbox->GList[y].LeftEdge,
  503.         sbox->GList[y].TopEdge,
  504.         sbox->GList[y].LeftEdge+sbox->GList[y].Width-1,
  505.         sbox->GList[y].TopEdge+sbox->GList[y].Height-1);
  506.         req->Window->RPort->BgPen=0;
  507.         SetDrMd (req->Window->RPort,JAM2);
  508.     }
  509.     if (entry) entry=entry->Next;
  510.     }
  511.     SetAPen (req->Window->RPort,oldfgpen);
  512.     SetBPen (req->Window->RPort,oldpen);
  513.     SetDrMd (req->Window->RPort,oldmode);
  514. }
  515.  
  516.  
  517.  
  518.  
  519. /* Any time new entries are added, or the selection status of
  520.  * an item is changed, call this function to update the SelectBox
  521. */
  522. void RefreshSBox (struct IGRequest *req,struct SelectBox *sb)
  523. {
  524.     struct IGPropInfo *pinfo;
  525.     USHORT count,x;
  526.     struct SelectBoxEntry *e;
  527.     struct IGSBoxGadgetInfo *ginfo;
  528.  
  529.     pinfo=(struct IGPropInfo *)sb->Prop->UserData;
  530.     ginfo=(struct IGSBoxGadgetInfo *)sb->GList->UserData;
  531.  
  532.     for (count=0,e=sb->Entries;e;e=e->Next,++count) e->ID=count;
  533.     for (x=0,e=sb->Entries;e && e->Next && x<pinfo->Top;e=e->Next,++x);
  534.     ModifyIGProp (req,sb->Prop,0,count,0,sb->Displayed,pinfo->Top,0);
  535.     ginfo->Entry=e;
  536.     UpdateSBox (req,sb->Prop,0,pinfo->Top);
  537. }
  538.  
  539.  
  540.  
  541.  
  542. /* Called by IGRequest.  Insures that all SelectBoxEntries are properly
  543.  * numbered in their ID fields (Selectbox won't work otherwise).
  544.  * When adding entries and calling RefreshSBox, it is not necessary to
  545.  * call this function, as RefreshSBox also carries out this task
  546. */
  547. void FixIDs (struct SelectBoxEntry *first)
  548. {
  549.     USHORT i=0;
  550.     while (first) {
  551.     first->ID=i;
  552.     ++i;
  553.     first=first->Next;
  554.     }
  555. }
  556.  
  557. #endif /* SBOXES */
  558.  
  559.  
  560. /* Generates the necessary structures and SHORT values for a two pixel thick,
  561.  * two color box.  Returns pointer to first of two Border structures.  All
  562.  * information is allocated on the Remember key
  563. */
  564. struct Border *MakeBox (USHORT w,USHORT h,UBYTE c1,UBYTE c2,struct Remember **key)
  565. {
  566.     struct Border *b,*d;
  567.     SHORT *f,*j;
  568.  
  569.     b=(struct Border *)AllocRemember (key,sizeof(struct Border)*2,MEMF_PUBLIC | MEMF_CLEAR);
  570.     if (!b) return (0);
  571.     f=(SHORT *)AllocRemember (key,48,MEMF_PUBLIC | MEMF_CLEAR);
  572.     if (!f) return (0);
  573.     d=&b[1];
  574.     j=&f[12];
  575.  
  576.     b->DrawMode=JAM1;
  577.     b->Count=6;
  578.     *d=*b;
  579.  
  580.     b->XY=f;
  581.     d->XY=j;
  582.     d->FrontPen=c2;
  583.     b->FrontPen=c1;
  584.     b->NextBorder=d;
  585.  
  586.     f[1]=j[3]=j[5]=h;
  587.     f[4]=j[0]=j[2]=w;
  588.     f[7]=f[8]=f[9]=f[10]=j[6]=j[11]=1;
  589.     f[6]=j[8]=j[10]=w-1;
  590.     f[11]=j[7]=j[9]=h-1;
  591.  
  592.     return (b);
  593. }
  594.  
  595.  
  596. #ifdef SBOXES
  597.  
  598. /* Called by IGRequest to generate borders for any selectbox that doesn't have
  599.  * one.
  600. */
  601. BOOL MakeSBBorder (struct SelectBox *sb)
  602. {
  603.     USHORT w,h;
  604.     if (sb->BColor1==0 && sb->BColor2==0) return (0);
  605.     sb->SBoxBorder=MakeBox(sb->Width,sb->Displayed*10+6,sb->BColor1,sb->BColor2,&sb->SBKey);
  606.     if (!(sb->SBoxBorder)) return (1);
  607.     return (0);
  608. }
  609.  
  610.  
  611.  
  612.  
  613. /* Using an array of strings with num entries, generates a corresponding
  614.  * SelectBoxEntry list.  All entries' ItemSelected functions are set to func
  615. */
  616. struct SelectBoxEntry *MakeSBEntryList (struct Remember **key,
  617.                     char *items[],int num,
  618.                     void (*func) ())
  619.  
  620. {
  621.     struct SelectBoxEntry *e;
  622.     USHORT i;
  623.  
  624.     e=(struct SelectBoxEntry *)AllocRemember (key,
  625.     sizeof(struct SelectBoxEntry)*num,MEMF_PUBLIC);
  626.     if (!e) return(0);
  627.     for (i=0;i<num;++i) {
  628.     e[i].Text=(UBYTE *)items[i];
  629.     e[i].ID=i;
  630.     e[i].Flags=0;
  631.     e[i].ItemSelected=func;
  632.     e[i].Next=&e[i+1];
  633.     e[i].Prev=&e[i-1];
  634.     e[i].Color=1;
  635.     }
  636.     e[0].Prev=0;
  637.     e[i-1].Next=0;
  638.     return (e);
  639. }
  640.  
  641.  
  642.  
  643.  
  644. /* Insures that all SelecBoxEntries in list are doubly linked.
  645.  * Enables programmer to to define entries in source, singly linking them.
  646.  * Automatically called by IGRequest
  647. */
  648. void FixLinks (struct SelectBoxEntry *first)
  649. {
  650.     struct SelectBoxEntry *p;
  651.     if (!first) return ();
  652.     first->Prev=0;
  653.     p=first;
  654.     first=first->Next;
  655.     while (first) {
  656.     first->Prev=p;
  657.     p=first;
  658.     first=first->Next;
  659.     }
  660. }
  661.  
  662.  
  663.  
  664.  
  665. /* Adds a SelectBoxEntry to a SelectBox and a given position */
  666. void AddSBEntry (struct SelectBox *sb,struct SelectBoxEntry *toadd,int pos)
  667. {
  668.     SHORT i=0;
  669.     struct SelectBoxEntry *e;
  670.  
  671.     if (pos>0) --pos;
  672.  
  673.     e=sb->Entries;
  674.  
  675.     while (e && e->Next && i<pos) {
  676.     e=e->Next;
  677.     ++i;
  678.     }
  679.  
  680.     if (!e) i=-1;
  681.  
  682.     if (i<pos || i==-1) {
  683.     ++i;
  684.     while (e && e->Next) e=e->Next;
  685.     if (e) e->Next=toadd;
  686.     toadd->Prev=e;
  687.     toadd->Next=0;
  688.     } else {
  689.     toadd->Prev=e->Prev;
  690.     if (toadd->Prev) toadd->Prev->Next=toadd;
  691.     toadd->Next=e;
  692.     e->Prev=toadd;
  693.     }
  694.     if (i==0) sb->Entries=toadd;
  695.     FixIDs (sb->Entries);
  696. }
  697.  
  698.  
  699.  
  700.  
  701. void AddSBEntryAlpha (struct SelectBox *sb,struct SelectBoxEntry *entry)
  702. {
  703.     struct SelectBoxEntry *e;
  704.     USHORT i=1;
  705.  
  706.     e=sb->Entries;
  707.  
  708.     if (!e) {
  709.     AddSBEntry (sb,entry,0);
  710.     return ();
  711.     }
  712.  
  713.     while (e && stricmp (e->Text,entry->Text)<0) {
  714.     e=e->Next;
  715.     ++i;
  716.     }
  717.     AddSBEntry (sb,entry,i);
  718. }
  719.  
  720.  
  721.  
  722.  
  723. /* Creates a SelectBoxEntry for a given string, then calls AddSBEntry.
  724.  * Entry is allocated on Remembery key, Returns 1 on error,
  725.  * 0 for success.
  726. */
  727. BOOL AddEntry (struct SelectBox *sb,
  728.            char *entry, void (*func) (),
  729.            int pos)
  730. {
  731.     struct SelectBoxEntry *e;
  732.  
  733.     e=(struct SelectBoxEntry *)AllocMem (sizeof(struct SelectBoxEntry),
  734.     MEMF_CLEAR | MEMF_PUBLIC);
  735.     if (!e) return (1);
  736.  
  737.     e->Text=entry;
  738.     e->ItemSelected=func;
  739.     e->Flags=0;
  740.     e->Color=1;
  741.     AddSBEntry (sb,e,pos);
  742.     return (0);
  743. }
  744.  
  745.  
  746.  
  747.  
  748. /* Same as above, but places Entry in alphabetical order */
  749. BOOL AddEntryAlpha (struct SelectBox *sb,
  750.             char *entry, void (*func) () )
  751. {
  752.     struct SelectBoxEntry *e;
  753.     USHORT i=1;
  754.  
  755.     e=sb->Entries;
  756.  
  757.     if (!e) return (AddEntry (sb,entry,func,0));
  758.  
  759.     while (e && stricmp (e->Text,entry)<0) {
  760.     e=e->Next;
  761.     ++i;
  762.     }
  763.     return (AddEntry (sb,entry,func,i));
  764. }
  765.  
  766. void RemoveSBEntry (struct SelectBox *sb,struct SelectBoxEntry *e)
  767. {
  768.     if (e->Next) e->Next->Prev=e->Prev;
  769.     if (e->Prev) e->Prev->Next=e->Next;
  770.     if (sb->Entries==e) sb->Entries=e->Next;
  771.     if (sb->Selected==e) sb->Selected=0;
  772.     e->Next=e->Prev=0;
  773.     FixIDs (sb->Entries);
  774. }
  775.  
  776. void FreeSBEntry (struct SelectBoxEntry *e)
  777. {
  778.     FreeMem (e,sizeof (struct SelectBoxEntry));
  779. }
  780.  
  781. void ClearSBox (struct SelectBox *sb,BOOL free)
  782. {
  783.     struct SelectBoxEntry *e;
  784.     struct Gadget *prop;
  785.     struct IGPropInfo *pinfo;
  786.  
  787.     e=sb->Entries;
  788.     while (e) {
  789.     RemoveSBEntry (sb,e);
  790.     if (free) FreeSBEntry (e);
  791.     e=sb->Entries;
  792.     }
  793.     prop=sb->Prop;
  794.     pinfo=(struct IGPropInfo *)prop->UserData;
  795.     pinfo->MaxY=pinfo->Top=0;
  796. }
  797.  
  798. void SBoxSelectAll (struct SelectBox *sb)
  799. {
  800.     struct SelectBoxEntry *e;
  801.  
  802.     e=sb->Entries;
  803.     if (!e) return();
  804.     while (e->Next) {
  805.     e->Flags|=SB_SELECTED;
  806.     e=e->Next;
  807.     }
  808.     e->Flags|=SB_SELECTED;
  809.     sb->Selected=e;
  810. }
  811.  
  812. void SBoxDSelectAll (struct SelectBox *sb)
  813. {
  814.     struct SelectBoxEntry *e;
  815.  
  816.     e=sb->Entries;
  817.     while (e) {
  818.     FLAGOFF(e->Flags,SB_SELECTED);
  819.     e=e->Next;
  820.     }
  821.     sb->Selected=0;
  822. }
  823.  
  824. #endif /* SBOXES */
  825.  
  826.  
  827. /* For removing a Gadget from the IGRequest's Gadget list that was
  828.    added by an IGObject.  This will normally be called by that
  829.    object's cleanup routine.  IT CANNOT BE CALLED WHILE THE REQUESTER
  830.    IS ACTIVE (ON SCREEN).
  831.  
  832.    The Following IGRemove functions perform similar functions, just
  833.    on a different structure category.
  834. */
  835. void IGRemoveGadget (struct IGRequest *req,struct Gadget *rm)
  836. {
  837.     struct Gadget *n;
  838.     if (req->Gadgets==rm) {
  839.     req->Gadgets=rm->NextGadget;
  840.     rm->NextGadget=0;
  841.     } else {
  842.     for (n=req->Gadgets;n->NextGadget;n=n->NextGadget)
  843.         if (n->NextGadget==rm) {
  844.         n->NextGadget=rm->NextGadget;
  845.         rm->NextGadget=0;
  846.         break;
  847.         }
  848.     }
  849. }
  850.  
  851. void IGRemoveBorder (struct IGRequest *req,struct Border *rm)
  852. {
  853.     struct Border *n;
  854.     if (req->Borders==rm) {
  855.     req->Borders=rm->NextBorder;
  856.     rm->NextBorder=0;
  857.     } else {
  858.     for (n=req->Borders;n->NextBorder;n=n->NextBorder)
  859.         if (n->NextBorder==rm) {
  860.         n->NextBorder=rm->NextBorder;
  861.         rm->NextBorder=0;
  862.         break;
  863.         }
  864.     }
  865. }
  866.  
  867. void IGRemoveImage (struct IGRequest *req,struct Image *rm)
  868. {
  869.     struct Image *n;
  870.     if (req->Images==rm) {
  871.     req->Images=rm->NextImage;
  872.     rm->NextImage=0;
  873.     } else {
  874.     for (n=req->Images;n->NextImage;n=n->NextImage)
  875.         if (n->NextImage==rm) {
  876.         n->NextImage=rm->NextImage;
  877.         rm->NextImage=0;
  878.         break;
  879.         }
  880.     }
  881. }
  882.  
  883. void IGRemoveIText (struct IGRequest *req,struct IntuiText *rm)
  884. {
  885.     struct IntuiText *n;
  886.     if (req->ITexts==rm) {
  887.     req->ITexts=rm->NextText;
  888.     rm->NextText=0;
  889.     } else {
  890.     for (n=req->ITexts;n->NextText;n=n->NextText)
  891.         if (n->NextText==rm) {
  892.         n->NextText=rm->NextText;
  893.         rm->NextText=0;
  894.         break;
  895.         }
  896.     }
  897. }
  898.  
  899. void IGRemoveSBox (struct IGRequest *req,struct SelectBox *rm)
  900. {
  901.     struct SelectBox *n;
  902.     if (req->SBoxes==rm) {
  903.     req->SBoxes=rm->Next;
  904.     rm->Next=0;
  905.     } else {
  906.     for (n=req->SBoxes;n->Next;n=n->Next)
  907.         if (n->Next==rm) {
  908.         n->Next=rm->Next;
  909.         rm->Next=0;
  910.         break;
  911.         }
  912.     }
  913. }
  914.  
  915. void IGRemoveIGObject (struct IGRequest *req,struct IGObject *rm)
  916. {
  917.     struct IGObject *n;
  918.     if (req->IGObjects==rm) {
  919.     rm->Next->Prev=0;
  920.     req->IGObjects=rm->Next;
  921.     rm->Next=0;
  922.     } else {
  923.     for (n=req->IGObjects;n->Next;n=n->Next)
  924.         if (n->Next==rm) {
  925.         rm->Next->Prev=n;
  926.         n->Next=rm->Next;
  927.         rm->Next=rm->Prev=0;
  928.         break;
  929.         }
  930.     }
  931. }
  932.  
  933.  
  934. /* Procedure IGFromStruct */
  935. /* Copies values from datastructure into the requester Gadgets */
  936.  
  937. void IGFromStruct (ULONG ds,struct Gadget *gadg)
  938. {
  939.     struct IGStringInfo *igsinfo;
  940.     struct IGBoolInfo *binfo;
  941.     struct StringInfo *sinfo;
  942.  
  943.     if (!ds || !gadg) return ();
  944.  
  945.     for (;gadg;gadg=gadg->NextGadget) {
  946.     if ((gadg->GadgetType & GTYP_BOOLGADGET) &&
  947.         (gadg->Activation & GACT_TOGGLESELECT)) {
  948.         binfo=(struct IGBoolInfo *)gadg->UserData;
  949.         if (binfo && (binfo->Type & BOOL_FILL)) {
  950.             ULONG *field;
  951.             field=(ULONG *)(ds+binfo->DataStructOffSet);
  952.             if ((*field) & (1<<binfo->BitToSet)) {
  953.             gadg->Flags|=GFLG_SELECTED;
  954.             } else FLAGOFF (gadg->Flags,GFLG_SELECTED);
  955.         }
  956.     } else if (gadg->GadgetType & GTYP_STRGADGET) {
  957.         sinfo=(struct StringInfo *)gadg->SpecialInfo;
  958.         igsinfo=(struct IGStringInfo *) gadg->UserData;
  959.  
  960.         if (!sinfo || !igsinfo) continue;
  961.         if (igsinfo->Type & STRING_FILL) {
  962. #ifdef FLOATINGMATH
  963.         if (igsinfo->Type & STRING_FLOAT) {
  964.             IGFloat *p;
  965.             p=(IGFloat *)(ds+igsinfo->DataStructOffSet);
  966.             FloatToString (sinfo->Buffer,*p);
  967.         }
  968. #endif /* FLOATINGMATH */
  969.         if (igsinfo->Type & (STRING_SHORT | STRING_LONG)) {
  970.             LONG *l;
  971.             SHORT *s;
  972.             if (igsinfo->Type & STRING_SHORT) {
  973.             s=(SHORT *)(ds+igsinfo->DataStructOffSet);
  974.             LongToString (sinfo->Buffer,*s);
  975.             } else {
  976.             l=(LONG *)(ds+igsinfo->DataStructOffSet);
  977.             LongToString (sinfo->Buffer,*l);
  978.             }
  979.         } else if (!(igsinfo->Type & STRING_FLOAT))
  980.             strcpy (sinfo->Buffer,ds+igsinfo->DataStructOffSet);
  981.         }
  982.     }
  983.     }
  984. }
  985.  
  986.  
  987.  
  988.  
  989. /* Procedure IGFillStruct */
  990. /* copies appropriate value into data struct ds for each IG string gadget
  991.  * in the gadget list
  992. */
  993.  
  994. void IGFillStruct (ULONG ds,struct Gadget *gadg)
  995. {
  996.     struct IGStringInfo *igsinfo;
  997.     struct IGBoolInfo *binfo;
  998.     struct StringInfo *sinfo;
  999.  
  1000.     if (!ds || !gadg) return ();
  1001.  
  1002.     for (;gadg;gadg=gadg->NextGadget) {
  1003.     if ((gadg->GadgetType & GTYP_BOOLGADGET) &&
  1004.         (gadg->Activation & GACT_TOGGLESELECT)) {
  1005.         binfo=(struct IGBoolInfo *)gadg->UserData;
  1006.         if (binfo && (binfo->Type & BOOL_FILL)) {
  1007.             ULONG *field;
  1008.             field=(ULONG *)(ds+binfo->DataStructOffSet);
  1009.             if (gadg->Flags & GFLG_SELECTED) (*field)|=1<<binfo->BitToSet;
  1010.             else FLAGOFF ((*field),1<<binfo->BitToSet);
  1011.         }
  1012.     } else if (gadg->GadgetType & GTYP_STRGADGET) {
  1013.         sinfo=(struct StringInfo *)gadg->SpecialInfo;
  1014.         igsinfo=(struct IGStringInfo *)gadg->UserData;
  1015.  
  1016.         if (!sinfo || !igsinfo) continue;
  1017.         if (igsinfo->Type & STRING_FILL) {
  1018. #ifdef FLOATINGMATH
  1019.         if (igsinfo->Type & STRING_FLOAT) {
  1020.             IGFloat x,*p;
  1021.             x=strtod (sinfo->Buffer,0);
  1022.             p=(IGFloat *)(ds+igsinfo->DataStructOffSet);
  1023.             *p=x;
  1024.         }
  1025. #endif /* FLOATINGMATH */
  1026.         if (igsinfo->Type & (STRING_SHORT | STRING_LONG)) {
  1027.             LONG x,*l;
  1028.             SHORT *s;
  1029.             x=strtol (sinfo->Buffer,0,10);
  1030.             if (igsinfo->Type & STRING_SHORT) {
  1031.             s=(SHORT *)(ds+igsinfo->DataStructOffSet);
  1032.             *s=x;
  1033.             } else {
  1034.             l=(LONG *)(ds+igsinfo->DataStructOffSet);
  1035.             *l=x;
  1036.             }
  1037.         } else if (!(igsinfo->Type & STRING_FLOAT))
  1038.             strcpy(ds+igsinfo->DataStructOffSet,sinfo->Buffer);
  1039.         }
  1040.     }
  1041.     }
  1042. }
  1043.  
  1044.  
  1045.  
  1046.  
  1047. /* For internal use by IGRequest, you probably will never need to
  1048.  * use this routine yourself
  1049. */
  1050.  
  1051. void StringGUp (struct IGRequest *req,struct Gadget *gadg)
  1052. {
  1053.     struct IGStringInfo *sinfo;
  1054.     struct StringInfo *strinfo;
  1055.     BOOL refresh=0;
  1056.  
  1057.     strinfo=(struct StringInfo *)gadg->SpecialInfo;
  1058.     sinfo=(struct IGStringInfo *)gadg->UserData;
  1059.  
  1060. #ifdef FLOATINGMATH
  1061.     if (sinfo->Type & STRING_FLOAT) {
  1062.     IGFloat fl;
  1063.     if (strelim(strinfo->Buffer,"-.0987654321",1))
  1064.         refresh=1;
  1065.     fl=strtod (strinfo->Buffer,0);
  1066.     if (sinfo->Type & STRING_HIGHLIMIT && fl>sinfo->StringHigh) {
  1067.         LongToString (strinfo->Buffer,sinfo->StringHigh);
  1068.         refresh=1;
  1069.     }
  1070.     if (sinfo->Type & STRING_LOWLIMIT && fl<sinfo->StringLow) {
  1071.         LongToString (strinfo->Buffer,sinfo->StringLow);
  1072.         refresh=1;
  1073.     }
  1074.     }
  1075. #endif /* FLOATINGMATH */
  1076.     if (sinfo->Type & (STRING_SHORT | STRING_LONG)) {
  1077.     LONG  lng;
  1078.     if (strelim(strinfo->Buffer,"-0987654321",1))
  1079.         refresh=1;
  1080.     lng=strtol (strinfo->Buffer,0,10);
  1081.     if (sinfo->Type & STRING_HIGHLIMIT && lng>sinfo->StringHigh) {
  1082.         LongToString (strinfo->Buffer,sinfo->StringHigh);
  1083.         refresh=1;
  1084.     }
  1085.     if (sinfo->Type & STRING_LOWLIMIT && lng<sinfo->StringLow) {
  1086.         LongToString (strinfo->Buffer,sinfo->StringLow);
  1087.         refresh=1;
  1088.     }
  1089.     } else if (!(sinfo->Type & STRING_FLOAT))
  1090.     if (strelim (strinfo->Buffer,sinfo->DisAllowedChars,0)) refresh=1;
  1091.  
  1092.     if (refresh) RefreshGList (gadg,req->Window,req->Requester,1);
  1093. }
  1094.  
  1095.  
  1096.  
  1097.  
  1098. #define FreeIntuiMsg(x) FreeMem(x,sizeof(struct IntuiMessage))
  1099.  
  1100. BOOL SendIntuiMsg (struct IGRequest *req,ULONG Class,ULONG Code,
  1101.             USHORT Qualifier,APTR IAddress)
  1102. {
  1103.     struct IntuiMessage *msg;
  1104.     ULONG secs,mics;
  1105.  
  1106.     if (!(req->IComPort)) return (1);
  1107.  
  1108.     if (!(Class & req->Window->IDCMPFlags)) return (0);
  1109.  
  1110.     msg=AllocMem (sizeof(struct IntuiMessage),MEMF_PUBLIC | MEMF_CLEAR);
  1111.     if (!msg) return (2);
  1112.  
  1113.     CurrentTime(&secs,&mics);
  1114.  
  1115.     msg->Class=Class;
  1116.     msg->Code=Code;
  1117.     msg->Qualifier=Qualifier;
  1118.     msg->IAddress=IAddress;
  1119.     msg->Seconds=secs;
  1120.     msg->Micros=mics;
  1121.     msg->MouseX=req->Window->MouseX;
  1122.     msg->MouseY=req->Window->MouseY;
  1123.     msg->IDCMPWindow=req->Window;
  1124.  
  1125.     PutMsg (req->IComPort,msg);
  1126.     return (0);
  1127. }
  1128.  
  1129.  
  1130.  
  1131.  
  1132. BYTE AllocCLBit (struct IGRequest *req)
  1133. {
  1134.     BYTE toreturn;
  1135.     for (toreturn=0;toreturn<32;++toreturn)
  1136.     if (!(req->LoopBitsUsed & (1<<toreturn))) break;
  1137.     if (toreturn==32) return (-1);
  1138.     req->LoopBitsUsed|=(1<<toreturn);
  1139.     return (toreturn);
  1140. }
  1141.  
  1142.  
  1143. void FreeCLBit (struct IGRequest *req,UBYTE bit)
  1144. {
  1145.     FLAGOFF(req->LoopBitsUsed,(1<<bit));
  1146. }
  1147.  
  1148.  
  1149.  
  1150.  
  1151. /* internal use */
  1152. void ClearIGOServiced (struct IGRequest *req)
  1153. {
  1154.     struct IGObject *igo;
  1155.     for (igo=req->IGObjects;igo;igo=igo->Next)
  1156.     igo->Serviced=0;
  1157. }
  1158.  
  1159.  
  1160. void StimulateGadget (struct IGRequest *req,struct Gadget *gadg)
  1161. {
  1162.     if (!(gadg->Flags & GFLG_DISABLED)) {
  1163.     if (gadg->GadgetType & GTYP_STRGADGET)
  1164.         ActivateGadget (gadg,req->Window,req->Requester);
  1165.     else if (gadg->GadgetType & GTYP_BOOLGADGET) {
  1166.         gadg->Flags^=GFLG_SELECTED;
  1167.         RefreshGList (gadg,req->Window,req->Requester,1);
  1168.         if (!(gadg->Activation & GACT_TOGGLESELECT)) {
  1169.         gadg->Flags^=GFLG_SELECTED;
  1170.         RefreshGList (gadg,req->Window,req->Requester,1);
  1171.         }
  1172.     }
  1173.     }
  1174. }
  1175.  
  1176.  
  1177. BOOL GadgetClick(struct IGRequest *req,struct Gadget *gadg)
  1178. {
  1179.     BOOL x=0;
  1180.  
  1181.     if (!(gadg->Flags & GFLG_DISABLED)) {
  1182.     if (gadg->Activation & GACT_IMMEDIATE)
  1183.         x|=SendIntuiMsg(req,IDCMP_GADGETDOWN,0,0,(APTR)gadg);
  1184.     if (!(gadg->GadgetType & GTYP_STRGADGET)) {
  1185.         if (gadg->Activation & GACT_RELVERIFY)
  1186.         x|=SendIntuiMsg(req,IDCMP_GADGETUP,0,0,(APTR)gadg);
  1187.     }
  1188.     if (x) return (x);
  1189.     StimulateGadget (req,gadg);
  1190.     }
  1191.     return (0);
  1192. }
  1193.  
  1194.  
  1195.  
  1196.  
  1197. BOOL KeyClick (struct IGRequest *req,UBYTE *keyinfo,UBYTE key)
  1198. {
  1199.     USHORT qual=0,rk;
  1200.     if (cismember('a',keyinfo)) qual|=0x10;
  1201.     if (cismember('A',keyinfo)) qual|=0x40;
  1202.     if (cismember('s',keyinfo)) qual|=0x01;
  1203.     if (cismember('c',keyinfo)) qual|=0x08;
  1204.  
  1205.     rk=ASCIIToRawKey(key);
  1206.     if (rk==-1) return (3);
  1207.     return (SendIntuiMsg(req,IDCMP_RAWKEY,rk,qual,0));
  1208. }
  1209.  
  1210.  
  1211.  
  1212. #ifdef REXX
  1213.  
  1214. struct Gadget *FindRexxGadget (struct Gadget *gadg,UBYTE *name)
  1215. {
  1216.     struct IGBoolInfo *binfo;
  1217.     struct IGStringInfo *sinfo;
  1218.  
  1219.     for (;gadg;gadg=gadg->NextGadget) {
  1220.     if (gadg->GadgetType & GTYP_BOOLGADGET) {
  1221.         binfo=gadg->UserData;
  1222.         if (binfo)
  1223.         if (!stricmp(binfo->RexxName,name)) break;
  1224.     } else if (gadg->GadgetType & GTYP_STRGADGET) {
  1225.         sinfo=gadg->UserData;
  1226.         if (sinfo)
  1227.         if (!stricmp(sinfo->RexxName,name)) break;
  1228.     }
  1229.     }
  1230.     return (gadg);
  1231. }
  1232.  
  1233.  
  1234.  
  1235.  
  1236. struct IGMenu *FindRexxMenu (struct IGRequest *req,UBYTE *name)
  1237. {
  1238.     struct IGMenu *igm;
  1239.  
  1240.     igm=req->Menus;
  1241.  
  1242.     for (;igm->Code;++igm)
  1243.     if (!stricmp(igm->RexxName,name)) break;
  1244.     if (!(igm->Function)) igm=0;
  1245.     return (igm);
  1246. }
  1247.  
  1248. #endif /* REXX */
  1249.  
  1250.  
  1251.  
  1252.  
  1253. BOOL MenuPick (struct IGRequest *req,struct IGMenu *igm)
  1254. {
  1255.     BOOL result;
  1256.     result=SendIntuiMsg (req,IDCMP_MENUPICK,igm->Code,0,0);
  1257.     return result;
  1258. }
  1259.  
  1260.  
  1261.  
  1262.  
  1263.  
  1264. void SetStringGad (struct IGRequest *req,struct Gadget *gadg,UBYTE *string)
  1265. {
  1266.     struct StringInfo *info;
  1267.  
  1268.     if (!(gadg->GadgetType & GTYP_STRGADGET)) return;
  1269.  
  1270.     info=(struct StringInfo *)gadg->SpecialInfo;
  1271.     strcpy (info->Buffer,string);
  1272.     info->BufferPos=info->DispPos=0;
  1273.     RefreshGList (gadg,req->Window,req->Requester,1);
  1274.     SendIntuiMsg (req,IDCMP_GADGETDOWN,0,0,gadg);
  1275.     SendIntuiMsg (req,IDCMP_GADGETUP,0,0,gadg);
  1276. }
  1277.  
  1278.  
  1279. #ifdef REXX
  1280.  
  1281. #define RxPullWord(rxcom,combuf,ndx,len) \
  1282.     PullWordIndex(rxcom,combuf,ndx," ,","",len)
  1283.  
  1284. LONG PullWordIndex (UBYTE *slist,UBYTE *word,USHORT index,
  1285.               UBYTE *delim,UBYTE *retdelim,USHORT len)
  1286. {
  1287.     USHORT i,quotes=0,b,x;
  1288.     UBYTE quotetypestack[10]; /* Up to 10 levels of nested quotes */
  1289.     SHORT qsx=-1;
  1290.  
  1291.     if (!slist[index]) return (index);
  1292.     i=index;
  1293.  
  1294.     while (cismember(slist[i],delim)) ++i;
  1295.     for (b=i;slist[i] &&
  1296.          ( (!cismember(slist[i],delim) && !cismember(slist[i],retdelim) )
  1297.           || quotes);
  1298.              ++i) {
  1299.  
  1300.     if (slist[i]=='\'' || slist[i]=='\"') {
  1301.         if (qsx>-1 && slist[i]==quotetypestack[qsx]) {
  1302.         --qsx;
  1303.         if (qsx==-1) quotes=0;
  1304.         } else if (qsx<9) {
  1305.         ++qsx;
  1306.         quotetypestack[qsx]=slist[i];
  1307.         quotes=1;
  1308.         }
  1309.     }
  1310.     }
  1311.  
  1312.     if (b==i && cismember(slist[i],retdelim)) ++i;
  1313.  
  1314.     for (x=0;b<i;++x,++b) {
  1315.     if (x==len-1) break;
  1316.     word[x]=slist[b];
  1317.     }
  1318.     word[x]=0;
  1319.  
  1320.     return (i);
  1321. }
  1322.  
  1323. BOOL IGProcessRexxMsg (struct IGRequest *req,struct RexxMsg *rm)
  1324. {
  1325.     struct Gadget *gadg;
  1326.     UBYTE com[30],*rxcom;
  1327.     USHORT rk,ndx;
  1328.     UBYTE CommandStatus=0;
  1329.  
  1330.     rxcom=rm->rm_Args[0];
  1331.     if (!rxcom) return;
  1332.  
  1333.     ndx=RxPullWord(rxcom,com,0,30);
  1334.  
  1335.     if (!stricmp(com,"KEYCLICK")) {
  1336.     UBYTE arg1[30],arg2[4];
  1337.     ndx=RxPullWord(rxcom,arg1,ndx,30);
  1338.     ndx=RxPullWord(rxcom,arg2,ndx,4);
  1339.  
  1340.     if (arg1[0] && arg2[0]) {
  1341.         rm->rm_Result1=KeyClick (req,arg1,arg2[0]);
  1342.         if (rm->rm_Result1) rm->rm_Result1+=10;
  1343.     } else rm->rm_Result1=10;
  1344.  
  1345.     } else if (!stricmp(com,"GADGETCLICK")) {
  1346.     UBYTE arg1[50];
  1347.     ndx=RxPullWord(rxcom,arg1,ndx,50);
  1348.     if (arg1[0]) {
  1349.         gadg=FindRexxGadget(req->Gadgets,arg1);
  1350.         if (gadg) {
  1351.         rm->rm_Result1=GadgetClick(req,gadg);
  1352.         if (rm->rm_Result1) rm->rm_Result1+=10;
  1353.         } else CommandStatus=1;
  1354.     } else rm->rm_Result1=10;
  1355.  
  1356.     } else if (!stricmp(com,"SETSTRINGGAD")) {
  1357.     UBYTE arg1[50],arg2[200];
  1358.     ndx=RxPullWord(rxcom,arg1,ndx,50);
  1359.     ndx=RxPullWord(rxcom,arg2,ndx,200);
  1360.  
  1361.     if (arg1[0] && arg2[0]) {
  1362.         gadg=FindRexxGadget(req->Gadgets,arg1);
  1363.         if (gadg) {
  1364.         SetStringGad (req,gadg,arg2);
  1365.         } else CommandStatus=1;
  1366.     } else rm->rm_Result1=10;
  1367.  
  1368.     } else if (!stricmp(com,"MENUPICK")) {
  1369.     UBYTE arg1[100];
  1370.     ndx=RxPullWord(rxcom,arg1,ndx,100);
  1371.     if (arg1[0]) {
  1372.         struct IGMenu *igm;
  1373.         igm=FindRexxMenu(req,arg1);
  1374.         if (igm) MenuPick(req,igm);
  1375.         else CommandStatus=1;
  1376.     } else rm->rm_Result1=10;
  1377.  
  1378.     } else {
  1379.     struct IGObject *obj;
  1380.     BOOL processed=0;
  1381.     for (obj=req->IGObjects;obj;obj=obj->Next) {
  1382.         if (!stricmp(com,obj->RexxName)) {
  1383.         if (obj->RexxFunction) processed=(*(obj->RexxFunction)) (req,obj,rm);
  1384.         break;
  1385.         }
  1386.     }
  1387.     CommandStatus = !processed;
  1388.     }
  1389.  
  1390.     return (CommandStatus);
  1391. }
  1392.  
  1393. #endif /* REXX */
  1394.  
  1395.  
  1396.  
  1397.  
  1398. /*
  1399.     BlockIGInput Function opens an blank intuition requester on top
  1400.     of an IGRequest, thereby blocking its input
  1401. */
  1402. void BlockIGInput(struct IGRequest *req)
  1403. {
  1404.     struct IGPrivate *p;
  1405.  
  1406.     if (req && req->Window) {
  1407.     p=(struct IGPrivate *)req->InternalData;
  1408.     if (!(p->BlockedCount)) {
  1409.         struct Requester *areq;
  1410.  
  1411.         if (areq=AllocMem(sizeof(struct Requester),MEMF_PUBLIC | MEMF_CLEAR)) {
  1412.         Request(areq,req->Window);
  1413.         req->Flags|=IG_INPUTBLOCKED;
  1414.         p->BlockingReq=areq;
  1415.         ++p->BlockedCount;
  1416.         }
  1417.     } else ++p->BlockedCount;
  1418.     }
  1419. }
  1420.  
  1421.  
  1422.  
  1423.  
  1424. /*
  1425.     UnBlockIGInput closes blank requester opened by BlockIGInput, thereby
  1426.     permitting messages to come through again
  1427. */
  1428. void UnBlockIGInput(struct IGRequest *req)
  1429. {
  1430.     if (req && req->Flags & IG_INPUTBLOCKED) {
  1431.     struct IGPrivate *p;
  1432.  
  1433.     p=req->InternalData;
  1434.     --p->BlockedCount;
  1435.  
  1436.     if (!(p->BlockedCount)) {
  1437.         EndRequest(p->BlockingReq,req->Window);
  1438.         FreeMem(p->BlockingReq,sizeof(struct Requester));
  1439.         FLAGOFF(req->Flags,IG_INPUTBLOCKED);
  1440.         p->BlockingReq=0;
  1441.     }
  1442.     }
  1443. }
  1444.  
  1445.  
  1446.  
  1447.  
  1448. /*
  1449.     Adjust NewWindow Dimensions so that they fit on the screen
  1450. */
  1451. void FixNewWindowDimensions(struct NewWindow *nw,struct Screen *s)
  1452. {
  1453.     SHORT x;
  1454.  
  1455.     if (nw->LeftEdge+nw->Width>s->Width) {
  1456.     x=s->Width-nw->Width;
  1457.     if (x>=0) nw->LeftEdge=x;
  1458.     else {
  1459.         nw->LeftEdge=0;
  1460.         nw->Width=s->Width;
  1461.     }
  1462.     }
  1463.     if (nw->TopEdge+nw->Height>s->Height) {
  1464.     x=s->Height-nw->Height;
  1465.     if (x>=0) nw->TopEdge=x;
  1466.     else {
  1467.         nw->TopEdge=0;
  1468.         nw->Height=s->Height;
  1469.     }
  1470.     }
  1471. }
  1472.  
  1473.  
  1474.  
  1475.  
  1476. /*
  1477.     ClearWindow Function, clears inside of window to background (0)
  1478. */
  1479. void ClearWindow (struct Window *w)
  1480. {
  1481.     SHORT x,y,X,Y;
  1482.     BYTE oldpen;
  1483.     if (!w) return ();
  1484.     x=w->BorderLeft+1;
  1485.     y=w->BorderTop+1;
  1486.     X=w->Width;
  1487.     Y=w->Height;
  1488.     X-=w->BorderRight+1;
  1489.     Y-=w->BorderBottom+1;
  1490.     oldpen=w->RPort->FgPen;
  1491.     SetAPen (w->RPort,0);
  1492.     RectFill (w->RPort,x,y,X,Y);
  1493.     SetAPen (w->RPort,oldpen);
  1494. }
  1495.  
  1496.  
  1497. /* IGRequest Function, handles request for IGRequest req */
  1498.  
  1499. /* If you are trying to compile a small memory model program, IGRequest
  1500.     can be a lot of over head.    To make it __far, uncomment the next line.
  1501.     Make sure that you define IGFAR before you include IGRequest.h! */
  1502.  
  1503. #ifdef IGFAR
  1504.  
  1505. __far
  1506.  
  1507. #endif
  1508.  
  1509. struct IGEndList *IGRequest (struct IGRequest *req)
  1510. {
  1511.     BOOL OpenedWindow=0,OpenedRequester=0,AddedGadgets=0,AllocedStuff=0,
  1512.      PropInProgress=0;
  1513.     struct Gadget *DSel=0,*gadg,*prop,*DClick=0,*KeyPress=0;
  1514.     struct IntuiMessage msg,*msgp;
  1515.     struct IGEndList *el=0;
  1516.     ULONG Signals=0,DCSecs,DCMics,WaitSignals;
  1517.     USHORT i,GadgetYOffSet=0;
  1518.     struct IGPrivate igprivate;
  1519.  
  1520.     req->Terminate=0;
  1521.     FLAGOFF(req->Flags,IG_INPUTBLOCKED);
  1522.     req->InternalData=(APTR)&igprivate;
  1523.  
  1524.     igprivate.BlockedCount=0;
  1525.     igprivate.BlockingReq=0;
  1526.  
  1527.     if (!(req->Window)) {
  1528.     if (!(req->NewWindow)) goto error;
  1529.     if (req->NewWindow->Type != WBENCHSCREEN) {
  1530.         struct Screen *s;
  1531.         s=req->NewWindow->Screen;
  1532.         GadgetYOffSet=s->WBorTop + s->Font->ta_YSize - 9;
  1533.         req->NewWindow->Height+=GadgetYOffSet;
  1534.         FixNewWindowDimensions(req->NewWindow,s);
  1535.     } else {
  1536.         struct Screen s;
  1537.         GetScreenData(&s,sizeof(struct Screen),WBENCHSCREEN,0);
  1538.         GadgetYOffSet=s.WBorTop + s.Font->ta_YSize - 9;
  1539.         req->NewWindow->Height+=GadgetYOffSet;
  1540.         FixNewWindowDimensions(req->NewWindow,&s);
  1541.     }
  1542.  
  1543.     req->Window=OpenWindow (req->NewWindow);
  1544.     if (!(req->Window)) goto error;
  1545.     OpenedWindow=1;
  1546.     } else {
  1547.     struct Screen *s;
  1548.     s=req->Window->WScreen;
  1549.     GadgetYOffSet=s->WBorTop + s->Font->ta_YSize - 9;
  1550.     if (GadgetYOffSet) {
  1551.         struct Window *w;
  1552.         w=req->Window;
  1553.         if (!((ULONG)w->UserData & WUD_FIXEDSIZE)) {
  1554.         if (w->TopEdge+w->Height+GadgetYOffSet>s->Height) {
  1555.             SHORT x;
  1556.             x=w->TopEdge+w->Height+GadgetYOffSet-s->Height;
  1557.             if ((SHORT)w->TopEdge-x<0) {
  1558.             x=0-w->TopEdge;
  1559.             MoveWindow(w,0,x);
  1560.             SizeWindow(w,0,s->Height-w->Height);
  1561.             } else {
  1562.             MoveWindow(w,0,0-x);
  1563.             SizeWindow(w,0,GadgetYOffSet);
  1564.             }
  1565.         } else SizeWindow(w,0,GadgetYOffSet);
  1566.         w->UserData|=WUD_FIXEDSIZE;
  1567.         }
  1568.     }
  1569.     }
  1570.  
  1571.     SetWindowTitles(req->Window,-1,req->ScreenName);
  1572.  
  1573.     if (!(req->Requester)) {
  1574.     if ((req->Flags & IG_ADDGADGETS) && GadgetYOffSet) {
  1575.         struct Gadget *gadg;
  1576.         for (gadg=req->Gadgets;gadg;gadg=gadg->NextGadget)
  1577.         gadg->TopEdge+=GadgetYOffSet;
  1578.     }
  1579.     if (req->Borders) {
  1580.         if (GadgetYOffSet) {
  1581.         struct Border *bord;
  1582.         for (bord=req->Borders;bord;bord=bord->NextBorder)
  1583.             bord->TopEdge+=GadgetYOffSet;
  1584.         }
  1585.     }
  1586.     if (req->Images) {
  1587.         if (GadgetYOffSet) {
  1588.         struct Image *image;
  1589.         for (image=req->Images;image;image=image->NextImage)
  1590.             image->TopEdge+=GadgetYOffSet;
  1591.         }
  1592.     }
  1593.     if (req->ITexts) {
  1594.         if (GadgetYOffSet) {
  1595.         struct IntuiText *it;
  1596.         for (it=req->ITexts;it;it=it->NextText)
  1597.             it->TopEdge+=GadgetYOffSet;
  1598.         }
  1599.     }
  1600.     }
  1601.     if (req->IGObjects) {
  1602.     struct IGObject *igo,*prev;
  1603.     for (igo=req->IGObjects,prev=0;igo;igo=igo->Next) {
  1604.         igo->Prev=prev;
  1605.         prev=igo;
  1606.         igo->GadgetYOffSet=GadgetYOffSet;
  1607.         if (igo->InitFunction) {
  1608.         if ((*(igo->InitFunction)) (req,igo)) {
  1609.             goto error;
  1610.         }
  1611.         }
  1612.     }
  1613.     }
  1614.     if (req->KeyCommands) {
  1615.     struct IGKeyCommand *kc;
  1616.  
  1617.     for (kc=req->KeyCommands;kc->Gadget;++kc) {
  1618.         if (!(kc->Command) && (kc->ASCIICommand))
  1619.         kc->Command=ASCIIToRawKey(kc->ASCIICommand);
  1620.     }
  1621.     }
  1622.     if (!(req->ReqKey)) {
  1623.     struct StringInfo *sinfo;
  1624.     struct IGStringInfo *igsinfo;
  1625.  
  1626.     AllocedStuff=1;
  1627.  
  1628.     for (gadg=req->Gadgets;gadg;gadg=gadg->NextGadget) {
  1629.         if (gadg->GadgetType==GTYP_STRGADGET) {
  1630.  
  1631.         sinfo=(struct StringInfo *)gadg->SpecialInfo;
  1632.         igsinfo=(struct IGStringInfo *)gadg->UserData;
  1633.  
  1634.         if ( !(sinfo->Buffer) || (igsinfo->Type & STRING_ALLOC) ) {
  1635.             sinfo->Buffer=(UBYTE *)AllocRemember (&req->ReqKey,
  1636.                         sinfo->MaxChars,MEMF_PUBLIC | MEMF_CLEAR);
  1637.             if (!(sinfo->Buffer)) goto error;
  1638.             igsinfo->Type|=STRING_ALLOC;
  1639.             if (igsinfo->InitialValue) {
  1640.             strcpy (sinfo->Buffer,igsinfo->InitialValue);
  1641.             FLAGOFF (igsinfo->Type,STRING_INITONCE);
  1642.             }
  1643.         }
  1644.         }
  1645.     }
  1646.     }
  1647. #ifdef PROPS
  1648.     FixIGProps (req->Gadgets);
  1649. #endif /* PROPS */
  1650.  
  1651.     for (gadg=req->Gadgets;gadg;gadg=gadg->NextGadget) {
  1652.     struct StringInfo *sinfo;
  1653.     struct IGStringInfo *igsinfo;
  1654.     struct IGBoolInfo *igbinfo;
  1655.     struct IGPropInfo *igpinfo;
  1656.  
  1657.     igsinfo=(struct IGStringInfo *)gadg->UserData;
  1658.  
  1659. #ifdef PROPS
  1660.     if (gadg->GadgetType==GTYP_PROPGADGET) {
  1661.         igpinfo=(struct IGPropInfo *)igsinfo;
  1662.         ModifyIGProp (req,gadg,igpinfo->MaxX,igpinfo->MaxY,
  1663.         igpinfo->DisplayedX,igpinfo->DisplayedY,
  1664.         igpinfo->Top,igpinfo->Left);
  1665.     } else if ((igsinfo->Type & (STRING_INITONCE | STRING_INITALWAYS))) {
  1666. #else
  1667.  
  1668.     if ((igsinfo->Type & (STRING_INITONCE | STRING_INITALWAYS))) {
  1669. #endif /* PROPS */
  1670.         if (igsinfo->Type & GADG_STRING) {
  1671.         sinfo=(struct StringInfo *)gadg->SpecialInfo;
  1672.  
  1673.         if (igsinfo->InitialValue) {
  1674.             strcpy (sinfo->Buffer,igsinfo->InitialValue);
  1675.             FLAGOFF(igsinfo->Type,STRING_INITONCE);
  1676.         }
  1677.         } else if (igsinfo->Type & GADG_BOOL) {
  1678.         igbinfo=(struct IGBoolInfo *)igsinfo;
  1679.         if (igbinfo->InitialValue) gadg->Flags|=GFLG_SELECTED;
  1680.         else FLAGOFF(gadg->Flags,GFLG_SELECTED);
  1681.         FLAGOFF(igbinfo->Type,GADG_INITONCE);
  1682.         }
  1683.     }
  1684.     }
  1685.  
  1686.     if (!(req->Flags & IG_INITDATASTRUCT)) IGFromStruct ((ULONG)req->DataStruct,req->Gadgets);
  1687.     if (req->InitFunction) (*(req->InitFunction)) (req);
  1688.     if ((req->RequesterToOpen)) {
  1689.     if (req->Flags & IG_INITREQUESTERTOOPEN) {
  1690.         IGInitRequester (req->Window,req->RequesterToOpen,
  1691.         RSOF,RSOF,RTOF,RBOF);
  1692.         req->RequesterToOpen->ReqGadget=req->Gadgets;
  1693.         req->RequesterToOpen->ReqBorder=req->Borders;
  1694.         req->RequesterToOpen->ReqText=req->ITexts;
  1695.     }
  1696.     req->Requester=req->RequesterToOpen;
  1697.     if (!Request(req->RequesterToOpen,req->Window)) goto error;
  1698.     OpenedRequester=1;
  1699.     RefreshWindowFrame (req->Window);
  1700.     }
  1701.     if (!(req->Requester)) {
  1702.     if ((req->Flags & IG_ADDGADGETS)) {
  1703.         AddGList (req->Window,req->Gadgets,-1,-1,0);
  1704.         AddedGadgets=1;
  1705.     }
  1706.     RefreshWindowFrame (req->Window);
  1707.     if (req->Borders) {
  1708.         DrawBorder (req->Window->RPort,req->Borders,0,0);
  1709.     }
  1710.     if (req->Images) {
  1711.         DrawImage  (req->Window->RPort,req->Images,0,0);
  1712.     }
  1713.     if (req->ITexts) {
  1714.         PrintIText (req->Window->RPort,req->ITexts,0,0);
  1715.     }
  1716. #ifdef SBOXES
  1717.     if (req->SBoxes) {
  1718.         struct SelectBox *sb;
  1719.         struct IGSBoxGadgetInfo *sbinfo;
  1720.  
  1721.         sb=req->SBoxes;
  1722.         while (sb) {
  1723.         if (!(sb->IGObject)) sb->TopEdge+=GadgetYOffSet;
  1724.         sb->GList=AllocRemember(&sb->SBKey,
  1725.             sizeof(struct Gadget)*sb->Displayed,MEMF_PUBLIC | MEMF_CLEAR);
  1726.         if (!(sb->GList)) goto error;
  1727.         sbinfo=AllocRemember (&sb->SBKey,sizeof(struct IGSBoxGadgetInfo)*sb->Displayed,
  1728.             MEMF_PUBLIC | MEMF_CLEAR);
  1729.         if (!sbinfo) goto error;
  1730.         gadg=sb->GList;
  1731.         for (i=0;i<sb->Displayed;++i) {
  1732.             gadg[i].NextGadget=&gadg[i+1];
  1733.             gadg[i].TopEdge=sb->TopEdge+3+10*i;
  1734.             gadg[i].LeftEdge=sb->LeftEdge+3;
  1735.             gadg[i].Width=sb->Width-6;
  1736.             gadg[i].Height=10;
  1737.             gadg[i].Activation=sb->Flags & (SB_TOGGLEALL | SB_TOGGLEONE) ?
  1738.             GACT_TOGGLESELECT | GACT_RELVERIFY : GACT_RELVERIFY;
  1739.             gadg[i].GadgetID=0xFFFF;  /* reserved exclusively for SB Gadgets,
  1740.                            * to avoid mixing them up with others */
  1741.             gadg[i].GadgetType=GTYP_BOOLGADGET;
  1742.             gadg[i].UserData=(APTR)&sbinfo[i];
  1743.             sbinfo[i].Type=GADG_SBOX;
  1744.             sbinfo[i].SBox=sb;
  1745.         }
  1746.         gadg[i-1].NextGadget=0;
  1747.         sbinfo->Entry=sb->Entries;
  1748.         if (!(sb->SBoxBorder))
  1749.             if (MakeSBBorder (sb)) goto error;
  1750.         DrawBorder (req->Window->RPort,sb->SBoxBorder,sb->LeftEdge,sb->TopEdge);
  1751.         AddGList (req->Window,sb->GList,-1,-1,0);
  1752.         sb->Flags|=SB_ADDEDGADGETS;
  1753.         FixLinks (sb->Entries);
  1754.         RefreshSBox (req,sb);
  1755.         sb=sb->Next;
  1756.         }
  1757.     }
  1758. #endif /* SBOXES */
  1759.     }
  1760.  
  1761.     req->IComPort=CreatePort (0,0);
  1762.     if (!(req->IComPort)) goto error;
  1763.  
  1764.     if (req->StringToActivate) GadgetClick (req,req->StringToActivate);
  1765.     if (req->MenuStrip) SetMenuStrip (req->Window,req->MenuStrip);
  1766.  
  1767.     for (el=req->EndList;el->Class!=0xffffffff;++el);
  1768.  
  1769.     while (!(req->Terminate)) {
  1770.     USHORT rq=0;
  1771.  
  1772.     ClearIGOServiced (req);
  1773.  
  1774.     Signals|=SetSignal(0,0);
  1775.  
  1776. #ifdef REXX
  1777.     if (req->ArexxPort && (Signals & 1<<req->ArexxPort->mp_SigBit)) {
  1778.         struct RexxMsg *rm;
  1779.         rm=(struct RexxMsg *)GetMsg (req->ArexxPort);
  1780.         if (IGProcessRexxMsg(req,rm)) {
  1781.         if (req->ArexxFunction)
  1782.             (*(req->ArexxFunction)) (req,rm);
  1783.         else rm->rm_Result1=10;
  1784.         }
  1785.         ReplyMsg (rm);
  1786.         Signals ^= 1<<req->ArexxPort->mp_SigBit;
  1787.         continue;
  1788.     }
  1789. #endif /* REXX */
  1790.  
  1791.     if (!(msgp=(struct IntuiMessage *)GetMsg (req->Window->UserPort))) {
  1792.         if (!(msgp=(struct IntuiMessage *)GetMsg (req->IComPort))) {
  1793.         BOOL cont=0;
  1794.  
  1795.         if (req->SignalFunction)
  1796.             cont=(*(req->SignalFunction)) (req,Signals);
  1797.  
  1798.         if (req->CallLoop && req->LoopFunction) {
  1799.             (*(req->LoopFunction)) (req);
  1800.         } else if (!cont) {
  1801.             if (req->Terminate) break;
  1802.             WaitSignals=req->AdditionalSignals |
  1803.             1<<req->Window->UserPort->mp_SigBit |
  1804.             1<<req->IComPort->mp_SigBit;
  1805.             if (req->ArexxPort) WaitSignals |= 1<<req->ArexxPort->mp_SigBit;
  1806.             Signals=Wait ( WaitSignals );
  1807.         }
  1808.         continue;
  1809.         } else {
  1810.         msg=*msgp;
  1811.         FreeIntuiMsg(msgp);
  1812.         }
  1813.     } else {
  1814.         msg=*msgp;
  1815.         ReplyMsg (msgp);
  1816.     }
  1817.  
  1818. KeysBegin: ;
  1819.     if (msg.Qualifier & 7) rq=1;  /* shift */
  1820.     if (msg.Qualifier & 8) rq|=8; /* control */
  1821.     if (msg.Qualifier & 0x30) rq|=0x10; /* alt */
  1822.     if (msg.Qualifier & 0xc0) rq|=0x40; /* command (Amiga) */
  1823.     msg.Qualifier=rq;
  1824.  
  1825.     for (i=0;i<23;++i)
  1826.         if ((1<<i) & msg.Class) {
  1827.         void (**func) ();
  1828.         if (ftable[i]) {
  1829.             func=(ULONG)req+ftable[i];
  1830.                /* Previous line will generate a warning */
  1831.             if (*func) (**func) (req,&msg);
  1832.             break;
  1833.         }
  1834.         }
  1835.  
  1836.     if (req->OtherMessages) {
  1837.         struct MessageHandler *mh;
  1838.         for (mh=req->OtherMessages;mh;mh=mh->Next)
  1839.         if ((*mh->IsType) (req,&msg)) (mh->HandlerFunction) (req,&msg);
  1840.     }
  1841.     if (msg.Class & IDCMP_MENUPICK && req->Menus) {
  1842.         struct IGMenu *menus;
  1843.         for (menus=req->Menus;menus->Code;++menus)
  1844.         if (menus->Code==msg.Code) {
  1845.             (*(menus->Function)) (req,&msg);
  1846.             break;
  1847.         }
  1848.     }
  1849.  
  1850.     if ( DSel && ( msg.Class & ( IDCMP_MOUSEBUTTONS | IDCMP_GADGETDOWN | IDCMP_GADGETUP
  1851.             | IDCMP_RAWKEY | IDCMP_REQSET | IDCMP_CLOSEWINDOW | IDCMP_INACTIVEWINDOW) ) ) {
  1852.  
  1853.         struct IGStringInfo *info;
  1854.  
  1855.         info=(struct IGStringInfo *)DSel->UserData;
  1856.         StringGUp (req,DSel);
  1857.         if (req->DSelectFunction || (info && info->DSelectFunction)) {
  1858.         struct IntuiMessage cp;
  1859.         cp=msg;
  1860.         cp.Class=IDCMP_GADGETUP;
  1861.         cp.IAddress=(APTR)DSel;
  1862.         if (req->DSelectFunction) (*(req->DSelectFunction)) (req,&cp);
  1863.         if (info->DSelectFunction) (*(info->DSelectFunction)) (req,&cp);
  1864.         }
  1865.         DSel=0;
  1866.     }
  1867.  
  1868.     if ( (msg.Class & (IDCMP_GADGETUP | IDCMP_GADGETDOWN)) || PropInProgress ) {
  1869.         struct Gadget *nxtstr=0;
  1870.         struct IGBoolInfo *info;
  1871.         void (*gu) ()=0;
  1872.         void (*gd) ()=0;
  1873.  
  1874. #ifdef PROPS
  1875.         if (PropInProgress) {
  1876.         info=(struct IGBoolInfo *)gadg->UserData;
  1877.         goto handlearrow;
  1878.         }
  1879. #endif /* PROPS */
  1880.         gadg=(struct Gadget *)msg.IAddress;
  1881.         prop=gadg;
  1882.  
  1883.         if (gadg->UserData) {
  1884.         info=(struct IGBoolInfo *)gadg->UserData;
  1885.         if (info->Type & GADG_BOOL) {
  1886.             gu=info->GUpFunction;
  1887.             gd=info->GDownFunction;
  1888.             if (msg.Class & IDCMP_GADGETUP) {
  1889.             if (gadg==DClick) {
  1890.                 if (DoubleClick(DCSecs,DCMics,msg.Seconds,msg.Micros)) {
  1891.                 if (req->DoubleClick) (*(req->DoubleClick)) (req,&msg);
  1892.                 if (info->DClickFunction) (*(info->DClickFunction)) (req,&msg);
  1893.                 }
  1894.             }
  1895.             DClick=gadg;
  1896.             DCSecs=msg.Seconds;
  1897.             DCMics=msg.Micros;
  1898.             if (gadg->Activation & GACT_TOGGLESELECT) {
  1899.                 struct Gadget *tgadg;
  1900.  
  1901.                 if (gadg->Flags & GFLG_SELECTED &&
  1902.                   gadg->MutualExclude) {
  1903.  
  1904.                 tgadg=req->Gadgets;
  1905.                 while (tgadg) {
  1906.                     if (tgadg->Activation & GACT_TOGGLESELECT &&
  1907.                       tgadg->MutualExclude & gadg->MutualExclude &&
  1908.                       tgadg->Flags & GFLG_SELECTED &&
  1909.                       tgadg!=gadg) {
  1910.                     tgadg->Flags^=GFLG_SELECTED;
  1911.                     RefreshGList (tgadg,req->Window,
  1912.                      req->Requester,1);
  1913.                     }
  1914.                     tgadg=tgadg->NextGadget;
  1915.                 }
  1916.                 } else if (gadg->MutualExclude &&
  1917.                   info->Type & GADG_ONESELECTED) {
  1918.                 UBYTE somethingon=0;
  1919.                 tgadg=req->Gadgets;
  1920.                 while (tgadg) {
  1921.                     if (tgadg->Activation & GACT_TOGGLESELECT &&
  1922.                       tgadg->MutualExclude & gadg->MutualExclude &&
  1923.                       tgadg->Flags & GFLG_SELECTED) {
  1924.                     somethingon=1;
  1925.                     break;
  1926.                     }
  1927.                     tgadg=tgadg->NextGadget;
  1928.                 }
  1929.                 if (!somethingon) {
  1930.                     gadg->Flags|=GFLG_SELECTED;
  1931.                     RefreshGList(gadg,req->Window,
  1932.                       req->Requester,1);
  1933.                 }
  1934.                 }
  1935.             }
  1936.             }
  1937.         } else if (info->Type & GADG_STRING) {
  1938.             struct IGStringInfo *sinfo;
  1939.             sinfo=(struct IGStringInfo *)info;
  1940.             gu=sinfo->GUpFunction;
  1941.             gd=sinfo->GDownFunction;
  1942.             if (msg.Class & IDCMP_GADGETDOWN) DSel=gadg;
  1943.             else if (msg.Code!=0x09) nxtstr=sinfo->NextStringGadget;
  1944. #ifdef SBOXES
  1945.         } else if (info->Type & GADG_SBOX) {
  1946.             struct IGSBoxGadgetInfo *sinfo;
  1947.             struct SelectBoxEntry *entry;
  1948.  
  1949.             sinfo=(struct IGSBoxGadgetInfo *)info;
  1950.             entry=sinfo->Entry;
  1951.  
  1952.             if (entry) {
  1953.             void (*ItemFunc) ();
  1954.             void (*BoxFunc) ();
  1955.  
  1956.               if (!(entry->Flags & SB_SELECTED)) {
  1957.             if (sinfo->SBox->Flags & SB_TOGGLEONE && sinfo->SBox->Selected) {
  1958.                 struct SelectBoxEntry *e;
  1959.                 BYTE oldpen,oldmode;
  1960.                 e=sinfo->SBox->Selected;
  1961.                 e->Flags=0;
  1962.                 if (e->Gadget) {
  1963.                 oldpen=req->Window->RPort->BgPen;
  1964.                 oldmode=req->Window->RPort->DrawMode;
  1965.                 SetDrMd (req->Window->RPort,COMPLEMENT | JAM2 |
  1966.                     INVERSVID);
  1967.                 SetBPen (req->Window->RPort,1);
  1968.                 e->Gadget->Flags=GFLG_GADGHCOMP;
  1969.                 RectFill (req->Window->RPort,e->Gadget->LeftEdge,
  1970.                     e->Gadget->TopEdge,e->Gadget->LeftEdge+e->Gadget->Width-1,
  1971.                     e->Gadget->TopEdge+e->Gadget->Height-1);
  1972.                 SetDrMd (req->Window->RPort,oldmode);
  1973.                 SetBPen (req->Window->RPort,oldpen);
  1974.                 }
  1975.             }
  1976.             if (sinfo->SBox->Flags & (SB_TOGGLEONE | SB_TOGGLEALL))
  1977.                 entry->Flags=SB_SELECTED;
  1978.             sinfo->SBox->Selected=entry;
  1979.             ItemFunc=entry->ItemSelected;
  1980.             BoxFunc=sinfo->SBox->ItemSelected;
  1981.             if (BoxFunc)
  1982.                 (*BoxFunc) (req,sinfo->SBox,entry,&msg);
  1983.             if (ItemFunc)
  1984.                 (*ItemFunc) (req,sinfo->SBox,entry,&msg);
  1985.               } else {
  1986.             sinfo->SBox->Selected=0;
  1987.             entry->Flags=0;
  1988.             if (entry->Gadget) entry->Gadget->Flags=GFLG_GADGHCOMP;
  1989.             ItemFunc=entry->ItemDSelected;
  1990.             BoxFunc=sinfo->SBox->ItemDSelected;
  1991.             if (BoxFunc)
  1992.                 (*BoxFunc) (req,sinfo->SBox,entry,&msg);
  1993.             if (ItemFunc)
  1994.                 (*ItemFunc) (req,sinfo->SBox,entry,&msg);
  1995.               }
  1996.             } else if (sinfo->SBox->Flags & (SB_TOGGLEONE | SB_TOGGLEALL)) {
  1997.             BYTE oldpen,oldmode;
  1998.             gadg->Flags=GFLG_GADGHCOMP;
  1999.             oldpen=req->Window->RPort->BgPen;
  2000.             oldmode=req->Window->RPort->DrawMode;
  2001.             SetDrMd (req->Window->RPort,COMPLEMENT | JAM2 |
  2002.                 INVERSVID);
  2003.             SetBPen (req->Window->RPort,1);
  2004.             gadg->Flags=GFLG_GADGHCOMP;
  2005.             RectFill (req->Window->RPort,gadg->LeftEdge,
  2006.                 gadg->TopEdge,gadg->LeftEdge+gadg->Width-1,
  2007.                 gadg->TopEdge+gadg->Height-1);
  2008.             SetDrMd (req->Window->RPort,oldmode);
  2009.             SetBPen (req->Window->RPort,oldpen);
  2010.             }
  2011. #endif /* SBOXES */
  2012.         }
  2013. #ifdef PROPS
  2014. handlearrow:    if (info->Type & GADG_ARROW) {
  2015.             struct IGPropArrowInfo *arrow;
  2016.             struct IGPropInfo *igpinfo;
  2017.             struct PropInfo *pinfo;
  2018.             BOOL refresh=1;
  2019.             int n;
  2020.  
  2021.             arrow=(struct IGPropArrowInfo *)info;
  2022.             if (msg.Class & IDCMP_GADGETUP) {
  2023.             gu=arrow->GUpFunction;
  2024.             goto gadgdone;
  2025.             }
  2026.             if (arrow->GDownFunction && (msg.Class & IDCMP_GADGETDOWN))
  2027.             (*(arrow->GDownFunction)) (req,&msg);
  2028.             prop=arrow->Prop;
  2029.             pinfo=(struct PropInfo *)prop->SpecialInfo;
  2030.             igpinfo=(struct IGPropInfo *)prop->UserData;
  2031.  
  2032.  
  2033.             if ((pinfo->Flags & FREEVERT) && igpinfo->DisplayedY>igpinfo->MaxY)
  2034.             goto gadgdone;
  2035.             if ((pinfo->Flags & FREEHORIZ) && igpinfo->DisplayedX>igpinfo->MaxX)
  2036.             goto gadgdone;
  2037.  
  2038.             n=0xffff / (pinfo->Flags & FREEVERT ? igpinfo->MaxY :
  2039.                   igpinfo->MaxX);
  2040.  
  2041.             if (gadg==igpinfo->LUArrow) {
  2042.             if (pinfo->Flags & FREEVERT) {
  2043.                 if (pinfo->VertPot>=n)
  2044.                 pinfo->VertPot-=n;
  2045.                 else if (pinfo->VertPot>0) pinfo->VertPot=0;
  2046.                 else refresh=0;
  2047.             } else if (pinfo->Flags & FREEHORIZ) {
  2048.                 if (pinfo->HorizPot>=n)
  2049.                 pinfo->HorizPot-=n;
  2050.                 else if (pinfo->HorizPot>0) pinfo->HorizPot=0;
  2051.                 else refresh=0;
  2052.             }
  2053.             } else if (gadg==igpinfo->RDArrow) {
  2054.             if (pinfo->Flags & FREEVERT) {
  2055.                 if (pinfo->VertPot<=0xffff-n)
  2056.                 pinfo->VertPot+=n;
  2057.                 else if (pinfo->VertPot<0xffff) pinfo->VertPot=0xffff;
  2058.                 else refresh=0;
  2059.             } else if (pinfo->Flags & FREEHORIZ) {
  2060.                 if (pinfo->HorizPot<=0xffff-n)
  2061.                 pinfo->HorizPot+=n;
  2062.                 else if (pinfo->HorizPot<0xffff) pinfo->HorizPot=0xffff;
  2063.                 else refresh=0;
  2064.             }
  2065.             }
  2066.             if (refresh) RefreshGList (prop,req->Window,req->Requester,1);
  2067.             info->Type=GADG_PROP | GADG_ARROW;
  2068.         }
  2069. handleprop:    if (info->Type & GADG_PROP) {
  2070.             struct PropInfo *pinfo;
  2071.             struct IGPropInfo *igpinfo;
  2072.             ULONG top;
  2073.             BOOL change=0;
  2074.  
  2075.             igpinfo=(struct IGPropInfo *)prop->UserData;
  2076.             pinfo=(struct PropInfo *)prop->SpecialInfo;
  2077.             if (pinfo->Flags & FREEVERT) {
  2078.             if (igpinfo->MaxY>igpinfo->DisplayedY)
  2079.                 top=((ULONG)pinfo->VertPot * (igpinfo->MaxY-igpinfo->DisplayedY))/0xffff;
  2080.             else top=0;
  2081.             if (igpinfo->Top!=top) {
  2082.                 igpinfo->Top=top;
  2083.                 change=1;
  2084.             }
  2085.             }
  2086.             if (pinfo->Flags & FREEHORIZ) {
  2087.             if (igpinfo->MaxX>igpinfo->DisplayedX)
  2088.                 top=((ULONG)pinfo->HorizPot * (igpinfo->MaxX-igpinfo->DisplayedX))/0xffff;
  2089.             else top=0;
  2090.             if (igpinfo->Left!=top) {
  2091.                 igpinfo->Left=top;
  2092.                 change=1;
  2093.             }
  2094.             }
  2095.             if (change && igpinfo->ScrollFunc)
  2096.             (*(igpinfo->ScrollFunc)) (req,prop,igpinfo->Left,igpinfo->Top);
  2097.             if (msg.Class & IDCMP_GADGETUP) goto gadgdone;
  2098.             if (!(msgp=(struct IntuiMessage *)GetMsg(req->Window->UserPort)) ) {
  2099.             if (info->Type & GADG_ARROW) goto handlearrow;
  2100.             goto handleprop;
  2101.             }
  2102.             msg=*msgp;
  2103.             ReplyMsg (msgp);
  2104.             if (msg.Class & (IDCMP_GADGETUP | IDCMP_GADGETDOWN |
  2105.              IDCMP_MOUSEBUTTONS | IDCMP_REQSET |
  2106.              IDCMP_CLOSEWINDOW | IDCMP_INACTIVEWINDOW)) {
  2107.                 PropInProgress=0;
  2108.                 ClearIGOServiced (req);
  2109.                 goto KeysBegin;
  2110.             } else {
  2111.             PropInProgress=1;
  2112.             ClearIGOServiced (req);
  2113.             goto KeysBegin;
  2114.             }
  2115.         }
  2116. #endif /* PROPS */
  2117.  
  2118. gadgdone:    if (gd && msg.Class & IDCMP_GADGETDOWN) (*gd) (req,&msg);
  2119.         if (gu && msg.Class & IDCMP_GADGETUP) (*gu) (req,&msg);
  2120.         if (nxtstr) GadgetClick (req,nxtstr);
  2121.         }
  2122.     }
  2123.  
  2124.  
  2125. KeyPressGUp: ;
  2126.     if (msg.Class & IDCMP_RAWKEY) {
  2127.         struct IGKeyCommand *kc;
  2128.         for (kc=req->KeyCommands;kc->Gadget;++kc) {
  2129.         if (kc->Command==msg.Code && kc->Qualifier==msg.Qualifier)
  2130.             GadgetClick (req,kc->Gadget);
  2131.         }
  2132.     }
  2133.  
  2134.     for (el=req->EndList;el->Class!=0xffffffff;++el) {
  2135.         if ( ((el->Class & IDCMP_GADGETUP) && (msg.Class & IDCMP_GADGETUP))
  2136.         || ((el->Class & IDCMP_GADGETDOWN) && (msg.Class & IDCMP_GADGETDOWN)) ) {
  2137.             if (el->Gadget==(struct Gadget *)msg.IAddress) {
  2138.             if (el->OKToEnd) if (!(*(el->OKToEnd)) (req,&msg)) break;
  2139.             req->Terminate=el->FillStruct ? 1 : -1;
  2140.             break;
  2141.             }
  2142.         } else if (el->Class==msg.Class && el->Code==msg.Code
  2143.                && el->Qualifier==msg.Qualifier) {
  2144.             if (el->OKToEnd) if (!(*(el->OKToEnd)) (req,&msg)) break;
  2145.             req->Terminate=el->FillStruct ? 1 : -1;
  2146.             break;
  2147.         }
  2148.     }
  2149.     }
  2150.  
  2151.     if (req->Terminate>0) IGFillStruct ((ULONG)req->DataStruct,req->Gadgets);
  2152.  
  2153.     if (req->EndFunction) (*(req->EndFunction)) (req,&msg);
  2154.  
  2155.     if (el->Class!=0xffffffff) {
  2156.     if (el->Function) (*(el->Function)) (req,&msg);
  2157.     } else {
  2158.     el->FillStruct=req->Terminate;
  2159.     }
  2160.  
  2161.     goto done;
  2162.  
  2163. error: if (AllocedStuff) FreeRemember (&req->ReqKey,1);
  2164.        {
  2165.         struct IGObject *igo;
  2166.         for (igo=req->IGObjects;igo->Next;igo=igo->Next);
  2167.         for (;igo;igo=igo->Prev)
  2168.         if (igo->AbortFunction) (*(igo->AbortFunction)) (req,igo,0);
  2169.        }
  2170.        el=0;
  2171.  
  2172. done: ;
  2173.     if (OpenedRequester) EndRequest (req->Requester,req->Window);
  2174. #ifdef SBOXES
  2175.     if (req->SBoxes) {
  2176.     struct SelectBox *sb;
  2177.     sb=req->SBoxes;
  2178.     while (sb) {
  2179.         if (!(sb->IGObject)) sb->TopEdge-=GadgetYOffSet;
  2180.         if (sb->Flags & SB_ADDEDGADGETS) {
  2181.         RemoveGList (req->Window,sb->GList,sb->Displayed);
  2182.         sb->Flags^=SB_ADDEDGADGETS;
  2183.         }
  2184.         sb->SBoxBorder=0;
  2185.  
  2186.         FreeRemember (&sb->SBKey,1);
  2187.         sb=sb->Next;
  2188.     }
  2189.     }
  2190. #endif SBOXES
  2191.     if (OpenedWindow) {
  2192.     if (req->Flags & IG_RECORDWINDOWPOS) {
  2193.         req->NewWindow->LeftEdge=req->Window->LeftEdge;
  2194.         req->NewWindow->TopEdge=req->Window->TopEdge;
  2195.         req->NewWindow->Width=req->Window->Width;
  2196.         req->NewWindow->Height=req->Window->Height;
  2197.     }
  2198.     CloseWindow (req->Window);
  2199.     req->NewWindow->Height-=GadgetYOffSet;
  2200.     req->Window=0;
  2201.     } else {
  2202.     RemoveGList(req->Window,req->Gadgets,-1);
  2203.     ClearWindow (req->Window);
  2204.     }
  2205.     if (req->IComPort) {
  2206.     while (msgp=GetMsg(req->IComPort))
  2207.         FreeIntuiMsg(msgp);
  2208.  
  2209.     DeletePort (req->IComPort);
  2210.     }
  2211.     if (el && req->IGObjects) {
  2212.     struct IGObject *igo;
  2213.     for (igo=req->IGObjects;igo->Next;igo=igo->Next);
  2214.     for (;igo;igo=igo->Prev)
  2215.         if (igo->RequestEndedFunction) (*(igo->RequestEndedFunction))
  2216.             (req,igo,el);
  2217.     }
  2218.  
  2219.     if ((req->Flags & IG_ADDGADGETS)) {
  2220.     if (GadgetYOffSet) {
  2221.         struct Gadget *gadg;
  2222.         for (gadg=req->Gadgets;gadg;gadg=gadg->NextGadget)
  2223.         gadg->TopEdge-=GadgetYOffSet;
  2224.     }
  2225.     }
  2226.     if (req->Borders) {
  2227.     if (GadgetYOffSet) {
  2228.         struct Border *bord;
  2229.         for (bord=req->Borders;bord;bord=bord->NextBorder)
  2230.         bord->TopEdge-=GadgetYOffSet;
  2231.     }
  2232.     }
  2233.     if (req->Images) {
  2234.     if (GadgetYOffSet) {
  2235.         struct Image *image;
  2236.         for (image=req->Images;image;image=image->NextImage)
  2237.         image->TopEdge-=GadgetYOffSet;
  2238.     }
  2239.     }
  2240.     if (req->ITexts) {
  2241.     if (GadgetYOffSet) {
  2242.         struct IntuiText *it;
  2243.         for (it=req->ITexts;it;it=it->NextText)
  2244.         it->TopEdge-=GadgetYOffSet;
  2245.     }
  2246.     }
  2247.  
  2248.     return (el);
  2249. }
  2250.  
  2251. static struct Gadget GadgTemplate =
  2252. {
  2253.     0,0,0,0,0,GFLG_GADGHIMAGE,GACT_RELVERIFY,GTYP_BOOLGADGET | GTYP_REQGADGET,
  2254.     0,0,0,0,0,0,0
  2255. };
  2256.  
  2257. BOOL BoolRequest (struct IGRequest *req,UBYTE *string,UBYTE *g1,UBYTE *g2)
  2258. {
  2259.     struct Remember *key=0;
  2260.     struct Requester areq;
  2261.     struct Gadget *gadg;
  2262.     struct IntuiText *it,*firsttext;
  2263.     UBYTE s[200],*c,flag=0;
  2264.     USHORT width,i,x,lines,n,t;
  2265.     ULONG  oldidcmp;
  2266.  
  2267.     if (!(req->Window)) return (1);
  2268.     width=req->Window->Width-20;
  2269.  
  2270.     it=(struct IntuiText *)AllocRemember (&key,sizeof (struct IntuiText),MEMF_PUBLIC);
  2271.     *it=Template;
  2272.     firsttext=it;
  2273.  
  2274.     i=n=strlen (string);
  2275.     while (i*8>width) i/=2;
  2276.     strcpy (s,string);
  2277.     for (lines=0,x=0;s[x] && !flag;++lines) {
  2278.     c=&s[x];
  2279.     for (x+=i,t=x; x<n && x && s[x]!=32;--x);
  2280.     if (x>=n) {
  2281.         x=n;
  2282.         flag=1;
  2283.     }
  2284.     if (!x) x=t;
  2285.     s[x++]=0;
  2286.     it->IText=c;
  2287.     it->LeftEdge=5;
  2288.     it->TopEdge=lines*10+5;
  2289.     if (!flag) {
  2290.         it->NextText=AllocRemember (&key,sizeof(struct IntuiText),MEMF_PUBLIC);
  2291.         it=it->NextText;
  2292.         *it=Template;
  2293.     }
  2294.     }
  2295.     width=(req->Window->Width-(8*i))/2-10;
  2296.     IGInitRequester (req->Window,&areq,width,width,RTOF,RBOF);
  2297.     areq.Height=(lines+2)*10+7;
  2298.     areq.LeftEdge=(req->Window->Width-areq.Width)/2;
  2299.     areq.TopEdge=(req->Window->Height-areq.Height)/2;
  2300.     areq.ReqBorder=MakeBox (areq.Width-1,areq.Height-1,2,1,&key);
  2301.     width=req->Window->Width-2*width;
  2302.     areq.ReqGadget=(struct Gadget *)AllocRemember(&key,sizeof(struct Gadget)*2,MEMF_PUBLIC);
  2303.     areq.ReqText=firsttext;
  2304.  
  2305.     gadg=areq.ReqGadget;
  2306.  
  2307.     c=g1;
  2308.     while (gadg) {
  2309.     *gadg=GadgTemplate;
  2310.     gadg->GadgetText=AllocRemember (&key,sizeof (struct IntuiText),MEMF_PUBLIC);
  2311.     *(gadg->GadgetText)=Template;
  2312.     gadg->GadgetText->IText=c;
  2313.     gadg->GadgetText->LeftEdge=10;
  2314.     gadg->GadgetText->TopEdge=3;
  2315.     gadg->GadgetRender=MakeBox (strlen(c)*8+20,12,2,1,&key);
  2316.     gadg->SelectRender=MakeBox (strlen(c)*8+20,12,1,2,&key);
  2317.     gadg->TopEdge=lines*10+10;
  2318.     gadg->LeftEdge= gadg==areq.ReqGadget ? 4 : width-4-(strlen(c)*8+20);
  2319.     gadg->Width=strlen(c)*8+20;
  2320.     gadg->Height=12;
  2321.     if (g1 && g2) areq.ReqGadget->NextGadget=&areq.ReqGadget[1];
  2322.     gadg=gadg->NextGadget;
  2323.     c=g2;
  2324.     }
  2325.  
  2326.     Request (&areq,req->Window);
  2327.     i=5;
  2328.     oldidcmp=req->Window->IDCMPFlags;
  2329.     ModifyIDCMP(req->Window,IDCMP_GADGETUP);
  2330.  
  2331.     FOREVER {
  2332.     struct IntuiMessage *msg;
  2333.     ULONG class;
  2334.     WaitPort (req->Window->UserPort);
  2335.     msg=(struct IntuiMessage *)GetMsg (req->Window->UserPort);
  2336.     class=msg->Class;
  2337.     gadg=(struct Gadget *)msg->IAddress;
  2338.     ReplyMsg (msg);
  2339.     if (gadg==areq.ReqGadget) i=0;
  2340.     else if (gadg==areq.ReqGadget->NextGadget) i=1;
  2341.     if (i<5) break;
  2342.     }
  2343.     EndRequest (&areq,req->Window);
  2344.     FreeRemember (&key,1);
  2345.     ModifyIDCMP(req->Window,oldidcmp);
  2346.     return (i);
  2347. }
  2348.  
  2349.